إطار عمل PHP صغير قوي وسهل الاستخدام مصمم لمساعدتك في إنشاء تطبيقات ويب ديناميكية وقوية - بسرعة!
يمنحك F3 (كما نسميه باعتزاز) بشكل مكثف في ملف واحد يبلغ حجمه 65 كيلو بايت تقريبًا، أساسًا متينًا وقاعدة تعليمات برمجية ناضجة ومنهجًا لا معنى له في كتابة تطبيقات الويب. يوجد تحت الغطاء مجموعة أدوات تطوير الويب سهلة الاستخدام، وتوجيه URL عالي الأداء ومحرك ذاكرة التخزين المؤقت، وتمييز التعليمات البرمجية المضمنة، ودعم التطبيقات متعددة اللغات. إنه خفيف الوزن وسهل الاستخدام وسريع. والأهم من ذلك كله، أنه لا يعيق طريقك.
سواء كنت مبتدئًا أو خبيرًا في برمجة PHP، فإن F3 سوف يساعدك على العمل في وقت قصير. لا توجد إجراءات تثبيت غير ضرورية ومضنية. لا يتطلب أي تكوين معقد. لا توجد هياكل دليل ملتوية. ليس هناك وقت أفضل لبدء تطوير تطبيقات الويب بالطريقة السهلة من الآن!
يدعم F3 قواعد بيانات SQL وNoSQL الجاهزة للاستخدام: MySQL، وSQLite، وMSSQL/Sybase، وPostgreSQL، وDB2، وMongoDB. كما أنه يأتي مزودًا بمصممي خرائط قويين مرتبطين بالكائنات لتجريد البيانات والنمذجة والتي تتميز بخفة الوزن مثل إطار العمل. لا حاجة للتكوين.
هذا ليس كل شيء. تم تزويد F3 بمكونات إضافية اختيارية أخرى تعمل على توسيع قدراته: -
على عكس الأطر الأخرى، يهدف F3 إلى أن يكون قابلاً للاستخدام - وليس عاديًا.
الفلسفة وراء الإطار ونهجه في هندسة البرمجيات هو نحو التقليل من المكونات الهيكلية، وتجنب تعقيد التطبيق وتحقيق التوازن بين أناقة التعليمات البرمجية وأداء التطبيق وإنتاجية المبرمج.
يتمتع F3 ببنية مستقرة على مستوى المؤسسات. أداء لا مثيل له، وميزات سهلة الاستخدام، ومساحة خفيفة الوزن. أكثر ما يمكن أن تسأل عنه؟ للحصول على هذه الحزمة، ما عليك سوى تنزيل هذه الحزمة أو زيارة مستودع Fatfree-core للعثور على أحدث إصدار.
لجميع مستخدمي الملحن هناك:
composer create-project bcosca/fatfree
composer require bcosca/fatfree-core
يوصى بشدة أن يقوم المستخدمون ذوو الخبرة بتطوير تطبيقات جديدة بأحدث إصدار للاستفادة من قاعدة التعليمات البرمجية المحدثة والتحسينات المستمرة.
يمكن العثور على أحدث دليل المستخدم ووثائق واجهة برمجة التطبيقات (API) التفصيلية مع الكثير من أمثلة التعليمات البرمجية والدليل الرسومي على موقع Fatfreeframework.com/.
بالطبع هذا المرجع المفيد عبر الإنترنت مدعوم من F3! ويعرض قدرة الإطار والأداء. التحقق من ذلك الآن. إذا كنت ترغب في قراءتها على github مباشرةً، فيمكنك العثور على محتوى مواقع الويب على github.com/F3Community/F3com-data
يعرف المصمم أنه قد وصل إلى الكمال ليس عندما لا يتبقى شيء ليضيفه، ولكن عندما لا يتبقى شيء ليأخذه. - أنطوان دو سانت إكزوبيري
يجعل Fat-Free Framework من السهل إنشاء مواقع ويب كاملة في لمح البصر. بنفس القوة والإيجاز اللذين تتمتع بهما مجموعات أدوات ومكتبات Javascript الحديثة، يساعدك F3 على كتابة برامج PHP ذات مظهر أفضل وأكثر موثوقية. نظرة واحدة على كود مصدر PHP الخاص بك وسيجد أي شخص أنه من السهل فهمه، ومدى قدرتك على إنجازه في عدد قليل جدًا من أسطر التعليمات البرمجية، ومدى قوة النتائج.
يعد F3 أحد أفضل الأطر الموثقة الموجودة. تعلم ذلك لا يكلف شيئا. لا توجد مجموعة صارمة من هياكل الدليل التي يصعب التنقل فيها وخطوات البرمجة الاقتحامية. لا توجد حمولة شاحنة من خيارات التكوين فقط لعرض 'Hello, World'
في متصفحك. يمنحك منتج Fat-Free قدرًا كبيرًا من الحرية - والأناقة - لإنجاز المزيد من العمل بسهولة وفي وقت أقل.
إن نهج F3 التعريفي في البرمجة يجعل من السهل على المبتدئين والخبراء على حد سواء فهم كود PHP. إذا كنت على دراية بلغة البرمجة Ruby، فستلاحظ التشابه بين إطار العمل الصغير Fat-Free وSinatra لأن كلاهما يستخدم لغة بسيطة خاصة بالمجال لخدمات الويب ReSTful. ولكن على عكس Sinatra وتجسيدات PHP (Fitzgerald، Limonade، Glue - على سبيل المثال لا الحصر)، فإن Fat-Free يتجاوز مجرد التعامل مع المسارات والطلبات. يمكن أن تكون طرق العرض بأي شكل من الأشكال، مثل نص عادي أو HTML أو XML أو رسالة بريد إلكتروني. يأتي الإطار مع محرك قالب سريع وسهل الاستخدام. يعمل F3 أيضًا بسلاسة مع محركات القوالب الأخرى، بما في ذلك Twig وSmarty وPHP نفسها. تتواصل النماذج مع مخططي البيانات في F3 ومساعد SQL لإجراء تفاعلات أكثر تعقيدًا مع محركات قواعد البيانات المختلفة. تعمل المكونات الإضافية الأخرى على توسيع الوظيفة الأساسية بشكل أكبر. إنه إطار عمل كامل لتطوير الويب - مع الكثير من القوة!
قم بفك ضغط محتويات حزمة التوزيع في أي مكان على محرك الأقراص الثابتة لديك. بشكل افتراضي، يوجد ملف إطار العمل والمكونات الإضافية الاختيارية في المسار lib/
. قم بتنظيم هياكل الدليل الخاصة بك بالطريقة التي تريدها. يمكنك نقل المجلدات الافتراضية إلى مسار لا يمكن الوصول إليه عبر الويب لتحسين الأمان. احذف المكونات الإضافية التي لا تحتاج إليها. يمكنك دائمًا استعادتها لاحقًا وسيكتشف F3 وجودها تلقائيًا.
هام: إذا كان تطبيقك يستخدم APC، أو Memcached، أو WinCache، أو XCache، أو ذاكرة تخزين مؤقت لنظام الملفات، فامسح جميع إدخالات ذاكرة التخزين المؤقت أولاً قبل استبدال الإصدار الأقدم من إطار العمل بإصدار جديد.
تأكد من أنك تقوم بتشغيل الإصدار الصحيح من PHP. لا يدعم F3 الإصدارات الأقدم من PHP 7.2. سوف تحصل على أخطاء في بناء الجملة (إيجابيات كاذبة) في كل مكان لأن بنيات اللغة الجديدة والإغلاقات/الوظائف المجهولة غير مدعومة بإصدارات PHP القديمة. لمعرفة ذلك، افتح وحدة التحكم الخاصة بك ( bash
shell على GNU/Linux، أو cmd.exe
على Windows):-
/path/to/php -v
ستخبرك PHP بالإصدار المحدد الذي تقوم بتشغيله ويجب أن تحصل على شيء يشبه هذا: -
PHP 7.4.21 (cli) (built: Jul 27 2021 15:56:07) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Xdebug v2.9.8, Copyright (c) 2002-2020, by Derick Rethans
قم بالترقية إذا لزم الأمر ثم عد إلى هنا إذا قمت بالانتقال إلى PHP 7.4 أو إصدار أحدث. يحتاج Fatfree إلى PHP 7.2 على الأقل ليعمل. إذا كنت بحاجة إلى مزود خدمة استضافة، جرب إحدى هذه الخدمات:
حان الوقت لبدء كتابة طلبنا الأول:-
$ f3 = require ( ' path/to/base.php ' );
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();
قم بإضافة base.php
في السطر الأول بالمسار المناسب. احفظ جزء التعليمات البرمجية أعلاه باسم ملف index.php
في مجلد جذر الويب الخاص بك. لقد كتبنا أول صفحة ويب لدينا.
باستخدام الملحن؟ ثم قم فقط بتشغيل composer require bcosca/fatfree
واستخدم ما يلي:
require ' vendor/autoload.php ' ;
$ f3 = Base:: instance ();
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();
يخبر الأمر الأول مترجم PHP أنك تريد أن تكون وظائف وميزات إطار العمل متاحة لتطبيقك. تُعلم الطريقة $f3->route()
Fat-Free أن صفحة الويب متاحة على عنوان URL النسبي المُشار إليه بالشرطة المائلة ( /
). أي شخص يزور موقعك الموجود على http://www.example.com/
سيرى الرسالة 'Hello, world!'
الرسالة لأن عنوان URL /
يعادل الصفحة الجذرية. لإنشاء مسار يتفرع من الصفحة الجذرية، مثل http://www.example.com/inside/
، يمكنك تحديد مسار آخر باستخدام سلسلة GET /inside
بسيطة.
يخبر المسار الموضح أعلاه إطار العمل بعرض الصفحة فقط عندما يتلقى طلب URL باستخدام طريقة HTTP GET
. تستخدم مواقع الويب الأكثر تعقيدًا والتي تحتوي على نماذج طرق HTTP أخرى مثل POST
، ويمكنك أيضًا تنفيذ ذلك كجزء من مواصفات $f3->route()
.
إذا رأى إطار العمل طلبًا واردًا لصفحة الويب الخاصة بك موجودًا على عنوان URL الجذر /
، فسيقوم تلقائيًا بتوجيه الطلب إلى وظيفة رد الاتصال، التي تحتوي على الكود الضروري لمعالجة الطلب وتقديم عناصر HTML المناسبة. في هذا المثال، قمنا فقط بإرسال السلسلة 'Hello, world!'
إلى متصفح الويب الخاص بالمستخدم.
لذلك أنشأنا طريقنا الأول. لكن هذا لن يفعل الكثير، باستثناء السماح لـ F3 بمعرفة أن هناك عملية ستتعامل معها وأن هناك بعض النصوص التي سيتم عرضها على متصفح الويب الخاص بالمستخدم. إذا كان لديك الكثير من الصفحات على موقعك، فستحتاج إلى إعداد مسارات مختلفة لكل مجموعة. في الوقت الحالي، دعونا نبقي الأمر بسيطًا. لتوجيه إطار العمل لبدء انتظار الطلبات، نصدر الأمر $f3->run()
.
لا يمكن تشغيل المثال؟ إذا كنت تواجه مشكلة في تشغيل هذا البرنامج البسيط على الخادم الخاص بك، فقد يتعين عليك تعديل إعدادات خادم الويب لديك قليلاً. ألقِ نظرة على نموذج تكوين Apache في القسم التالي (جنبًا إلى جنب مع مكافئات Nginx وLighttpd).
لا تزال تواجه مشكلة؟ تأكد من أن $f3 = require('path/to/base.php');
تأتي المهمة قبل أي إخراج في البرنامج النصي الخاص بك. يقوم base.php
بتعديل رؤوس HTTP، لذا فإن أي حرف يتم إخراجه إلى المتصفح قبل هذا التعيين سوف يسبب أخطاء.
لم يكن مثالنا الأول صعب الفهم، أليس كذلك؟ إذا كنت تحب المزيد من النكهة في الحساء الخالي من الدهون، فأدخل مسارًا آخر قبل الأمر $f3->run()
:-
$ f3 -> route ( ' GET /about ' ,
function () {
echo ' Donations go to a local charity... us! ' ;
}
);
ألا تريد فوضى مساحة الاسم العالمية بأسماء الوظائف؟ تتعرف Fat-Free على طرق مختلفة لتعيين معالجات المسار لفئات وطرق OOP: -
class WebPage {
function display () {
echo ' I cannot object to an object ' ;
}
}
$ f3 -> route ( ' GET /about ' , ' WebPage->display ' );
يمكن أيضًا توجيه طلبات HTTP إلى أساليب فئة ثابتة: -
$ f3 -> route ( ' GET /login ' , ' Auth::login ' );
يتم دائمًا توفير الوسائط التي تم تمريرها كمعلمة ثانية:
$ f3 -> route ( ' GET /hello/@name ' , ' User::greet ' );
class User {
public static function greet ( $ f3 , $ args ) { // $ args is type of Array
echo " Hello " . $ args [ ' name ' ];
}
}
إذا كانت وسيطة الاسم المقدمة هي foo (/hello/foo)، فسيتم عرض الإخراج التالي:
Hello foo
كدليل على اللغة القوية الخاصة بالمجال (DSL) الخاصة بـ Fat-Free، يمكنك تحديد طريق واحد للتعامل مع الاحتمالات المختلفة: -
$ f3 -> route ( ' GET /brew/@count ' ,
function ( $ f3 ) {
echo $ f3 -> get ( ' PARAMS.count ' ). ' bottles of beer on the wall. ' ;
}
);
يوضح هذا المثال كيف يمكننا تحديد رمز مميز @count
لتمثيل جزء من عنوان URL. سيخدم إطار العمل أي عنوان URL للطلب يطابق البادئة /brew/
، مثل /brew/99
و /brew/98
وما إلى ذلك. وسيعرض هذا '99 bottles of beer on the wall'
و '98 bottles of beer on the wall'
، على التوالى. ستقبل Fat-Free أيضًا طلب صفحة لـ /brew/unbreakable
. (توقع أن يؤدي هذا إلى عرض 'unbreakable bottles of beer on the wall'
.) عندما يتم تحديد مثل هذا المسار الديناميكي، يقوم Fat-Free تلقائيًا بملء متغير صفيف PARAMS
العام بقيمة السلاسل الملتقطة في عنوان URL. يسترد استدعاء $f3->get()
داخل وظيفة رد الاتصال قيمة متغير إطار العمل. يمكنك بالتأكيد تطبيق هذه الطريقة في التعليمات البرمجية الخاصة بك كجزء من العرض التقديمي أو منطق العمل. لكننا سنناقش ذلك بمزيد من التفصيل لاحقًا.
لاحظ أن Fat-Free يفهم تدوين نقاط المصفوفة. يمكنك استخدام التدوين العادي PARAMS['count']
بدلاً من ذلك في التعليمات البرمجية، وهو عرضة للأخطاء المطبعية والأقواس غير المتوازنة. في طرق العرض والقوالب، يسمح إطار العمل بتدوين @PARAMS.count
الذي يشبه إلى حد ما Javascript. (سنغطي طرق العرض والقوالب لاحقًا.)
إليك طريقة أخرى للوصول إلى الرموز المميزة في نمط الطلب: -
$ f3 -> route ( ' GET /brew/@count ' ,
function ( $ f3 , $ params ) {
echo $ params [ ' count ' ]. ' bottles of beer on the wall. ' ;
}
);
يمكنك استخدام العلامة النجمية ( *
) لقبول أي عنوان URL بعد المسار /brew
- إذا كنت لا تهتم حقًا ببقية المسار: -
$ f3 -> route ( ' GET /brew/* ' ,
function () {
echo ' Enough beer! We always end up here. ' ;
}
);
هناك نقطة مهمة يجب وضعها في الاعتبار: سوف تخلط بين Fat-Free (وأنت) إذا كان لديك كل من GET /brew/@count
و GET /brew/*
معًا في نفس التطبيق. استخدام واحد أو آخر. شيء آخر: ترى Fat-Free أن GET /brew
منفصل ومتميز عن المسار GET /brew/@count
. يمكن أن يكون لكل منها معالجات مسار مختلفة.
انتظر لحظة - في جميع الأمثلة السابقة، لم نقم أبدًا بإنشاء أي دليل على القرص الصلب الخاص بنا لتخزين هذه المسارات. الجواب القصير: ليس علينا أن نفعل ذلك. جميع طرق F3 افتراضية. إنها لا تعكس بنية مجلد القرص الثابت لدينا. إذا كان لديك برامج أو ملفات ثابتة (صور، CSS، وما إلى ذلك) لا تستخدم إطار العمل - طالما أن المسارات إلى هذه الملفات لا تتعارض مع أي مسار محدد في تطبيقك - فسيقوم برنامج خادم الويب الخاص بك بتسليمها إلى متصفح المستخدم، بشرط أن يتم تكوين الخادم بشكل صحيح.
عند تحديد طريق، يمكنك تعيين اسم له. استخدم اسم المسار في التعليمات البرمجية والقوالب الخاصة بك بدلاً من عنوان URL المكتوب. ثم إذا كنت بحاجة إلى تغيير عناوين URL الخاصة بك لإرضاء مسؤولي التسويق، فما عليك سوى إجراء التغيير حيث تم تحديد المسار. يجب أن تتبع أسماء المسارات قواعد تسمية متغيرات php (بدون نقاط أو شرطات أو واصلات).
دعونا نسمي الطريق:-
$ f3 -> route ( ' GET @beer_list: /beer ' , ' Beer->list ' );
يتم إدراج الاسم بعد المسار VERB ( GET
في هذا المثال) مسبوقًا بالرمز @
، ويتم فصله عن جزء URL بنقطتين :
الرمز. يمكنك إدراج مسافة بعد النقطتين إذا كان ذلك يسهل قراءة التعليمات البرمجية الخاصة بك (كما هو موضح هنا).
للوصول إلى المسار المسمى في قالب، احصل على قيمة المسار المسمى كمفتاح لمصفوفة خلية ALIASES
: -
< a href =" {{ @ALIASES.beer_list }} " > View beer list </ a >
لإعادة توجيه الزائر إلى عنوان URL جديد، اتصل بالمسار المسمى داخل طريقة reroute()
مثل: -
// a named route is a string value
$ f3 -> reroute ( ' @beer_list ' ); // note the single quotes
إذا كنت تستخدم الرموز المميزة في مسارك، فسيقوم F3 باستبدال تلك الرموز المميزة بقيمتها الحالية. إذا كنت تريد تغيير قيمة الرمز المميز قبل استدعاء إعادة التوجيه، فمررها كوسيطة ثانية.:-
$ f3 -> route ( ' GET @beer_list: /beer/@country ' , ' Beer->bycountry ' );
$ f3 -> route ( ' GET @beer_list: /beer/@country/@village ' , ' Beer->byvillage ' );
// a set of key - value pairs is passed as argument to named route
$ f3 -> reroute ( ' @beer_list(@country=Germany) ' );
// if more than one token needed
$ f3 -> reroute ( ' @beer_list(@country=Germany,@village=Rhine) ' );
تذكر استخدام urlencode()
وسيطاتك إذا كان لديك أحرف لا تتوافق مع إرشادات RFC 1738 لعناوين URL جيدة التنسيق.
يحتوي أحدث إصدار ثابت من PHP على خادم ويب مدمج خاص به. ابدأ تشغيله باستخدام التكوين التالي: -
php -S localhost:80 -t /var/www/
سيبدأ الأمر أعلاه في توجيه جميع الطلبات إلى جذر الويب /var/www
. إذا تم تلقي طلب HTTP وارد لملف أو مجلد، فسوف تبحث PHP عنه داخل جذر الويب وترسله إلى المتصفح إذا تم العثور عليه. بخلاف ذلك، سيقوم PHP بتحميل index.php
الافتراضي (الذي يحتوي على الكود الذي يدعم F3).
إذا كنت تستخدم Apache، فتأكد من تنشيط وحدة إعادة كتابة عنوان URL (mod_rewrite) في ملف apache.conf (أو httpd.conf). يجب عليك أيضًا إنشاء ملف .htaccess يحتوي على ما يلي: -
# Enable rewrite engine and route requests to framework
RewriteEngine On
# Some servers require you to specify the `RewriteBase` directive
# In such cases, it should be the path (relative to the document root)
# containing this .htaccess file
#
# RewriteBase /
RewriteRule ^(tmp)/|.ini$ - [R=404]
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L,QSA]
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
يخبر البرنامج النصي Apache أنه عندما يصل طلب HTTP وإذا لم يتم العثور على ملف فعلي ( !-f
) أو مسار ( !-d
) أو رابط رمزي ( !-l
) فإنه يجب نقل التحكم إلى index.php
الذي يحتوي على وحدة التحكم الرئيسية/الأمامية لدينا، والتي بدورها تستدعي إطار العمل.
يجب أن يكون .htaccess file
الذي يحتوي على توجيهات Apache المذكورة أعلاه موجودًا دائمًا في نفس المجلد مثل ملف index.php
.
تحتاج أيضًا إلى إعداد Apache حتى يعرف الموقع الفعلي لملف index.php
على محرك الأقراص الثابتة لديك. التكوين النموذجي هو: -
DocumentRoot " /var/www/html "
< Directory "/var/www/html">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
إذا كنت تقوم بتطوير عدة تطبيقات في وقت واحد، فمن الأسهل إدارة تكوين المضيف الظاهري: -
NameVirtualHost *
< VirtualHost *>
ServerName site1.com
DocumentRoot " /var/www/site1 "
< Directory "/var/www/site1">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
</ VirtualHost >
< VirtualHost *>
ServerName site2.com
DocumentRoot " /var/www/site2 "
< Directory "/var/www/site2">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
</ VirtualHost >
يجب إدراج كل ServerName
( site1.com
و site2.com
في مثالنا) في ملف /etc/hosts
الخاص بك. على نظام التشغيل Windows، يجب عليك تحرير C:/WINDOWS/system32/drivers/etc/hosts
. قد تكون إعادة التشغيل ضرورية لإحداث التغييرات. يمكنك بعد ذلك توجيه متصفح الويب الخاص بك إلى العنوان http://site1.com
أو http://site2.com
. تجعل المضيفات الافتراضية نشر تطبيقاتك أسهل بكثير.
بالنسبة لخوادم Nginx، إليك التكوين الموصى به (استبدل ip_address:port بإعدادات FastCGI PHP الخاصة ببيئتك):-
server {
root /var/www/html;
location / {
index index.php index.html index.htm;
try_files $uri $uri / /index.php? $query_string ;
}
location ~ .php$ {
fastcgi_pass ip_address:port;
include fastcgi_params;
}
}
يتم تكوين خوادم Lighttpd بطريقة مماثلة: -
$HTTP["host"] =~ "www.example.com$" {
url.rewrite-once = ( "^/(.*?)(?.+)?$"=>"/index.php/$1?$2" )
server.error-handler-404 = "/index.php"
}
قم بتثبيت وحدة إعادة كتابة عنوان URL وإطار عمل .NET المناسب المتوافق مع إصدار Windows لديك. ثم قم بإنشاء ملف باسم web.config
في جذر التطبيق الخاص بك بالمحتويات التالية:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Application" stopProcessing="true">
<match url=".*" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
لذلك دعونا نعود إلى الترميز. يمكنك إعلان أن الصفحة قديمة وإعادة توجيه زوار موقعك إلى موقع/صفحة أخرى:-
$ f3 -> route ( ' GET|HEAD /obsoletepage ' ,
function ( $ f3 ) {
$ f3 -> reroute ( ' /newpage ' );
}
);
إذا حاول شخص ما الوصول إلى عنوان URL http://www.example.com/obsoletepage
باستخدام طلب HTTP GET أو HEAD، فسيعيد إطار العمل توجيه المستخدم إلى عنوان URL: http://www.example.com/newpage
كما هو موضح في المثال أعلاه. يمكنك أيضًا إعادة توجيه المستخدم إلى موقع آخر، مثل $f3->reroute('http://www.anotherexample.org/');
.
يمكن أن تكون إعادة التوجيه مفيدة بشكل خاص عندما تحتاج إلى إجراء بعض أعمال الصيانة على موقعك. يمكن أن يكون لديك معالج مسار يُعلم زوار موقعك بأن موقعك غير متصل بالإنترنت لفترة قصيرة.
تعد عمليات إعادة توجيه HTTP أمرًا لا غنى عنه ولكنها قد تكون باهظة الثمن أيضًا. امتنع قدر الإمكان عن استخدام $f3->reroute()
لإرسال مستخدم إلى صفحة أخرى على نفس موقع الويب إذا كان بإمكانك توجيه تدفق التطبيق الخاص بك عن طريق استدعاء الوظيفة أو الطريقة التي تتعامل مع المسار المستهدف. ومع ذلك، لن يؤدي هذا الأسلوب إلى تغيير عنوان URL الموجود على شريط العناوين الخاص بمستعرض الويب الخاص بالمستخدم. إذا لم يكن هذا هو السلوك الذي تريده وتحتاج حقًا إلى إرسال مستخدم إلى صفحة أخرى، في حالات مثل الإرسال الناجح لنموذج أو بعد مصادقة المستخدم، يرسل Fat-Free رأس HTTP 302 Found
. بالنسبة لجميع المحاولات الأخرى لإعادة التوجيه إلى صفحة أو موقع آخر، يرسل إطار العمل رأس HTTP 301 Moved Permanently
.
في وقت التشغيل، يقوم Fat-Free تلقائيًا بإنشاء خطأ HTTP 404 عندما يرى أن طلب HTTP الوارد لا يتطابق مع أي من المسارات المحددة في التطبيق الخاص بك. ومع ذلك، هناك حالات تحتاج فيها إلى تشغيلها بنفسك.
خذ على سبيل المثال المسار المحدد بـ GET /dogs/@breed
. قد يتضمن منطق التطبيق الخاص بك البحث في قاعدة بيانات ومحاولة استرداد السجل المطابق لقيمة @breed
في طلب HTTP الوارد. نظرًا لأن Fat-Free ستقبل أي قيمة بعد البادئة /dogs/
بسبب وجود رمز @breed
، فإن عرض رسالة HTTP 404 Not Found
برمجيًا يصبح ضروريًا عندما لا يجد البرنامج أي تطابق في قاعدة البيانات الخاصة بنا. للقيام بذلك استخدم الأمر التالي:-
$ f3 -> error ( 404 );
تعتمد بنية Fat-Free على مفهوم أن عناوين URL لـ HTTP تمثل موارد ويب مجردة (لا تقتصر على HTML) ويمكن لكل مورد الانتقال من حالة تطبيق إلى أخرى. لهذا السبب، ليس لدى F3 أي قيود على الطريقة التي تقوم بها ببناء التطبيق الخاص بك. إذا كنت تفضل استخدام نمط Model-View-Controller، فيمكن أن يساعدك F3 في تجزئة مكونات تطبيقك للالتزام بهذا النموذج. من ناحية أخرى، يدعم الإطار أيضًا نمط تمثيل أسلوب المورد، ويكون تنفيذه أكثر وضوحًا.
فيما يلي مثال لواجهة ReST: -
class Item {
function get () {}
function post () {}
function put () {}
function delete () {}
}
$ f3 = require ( ' lib/base.php ' );
$ f3 -> map ( ' /cart/@item ' , ' Item ' );
$ f3 -> run ();
توفر طريقة $f3->map()
الخاصة بـ Fat-Free واجهة ReST عن طريق تعيين طرق HTTP في المسارات إلى الطرق المكافئة لكائن أو فئة PHP. إذا تلقى تطبيقك طلب HTTP واردًا مثل GET /cart/123
، فسيقوم Fat-Free بنقل التحكم تلقائيًا إلى طريقة get()
الخاصة بالكائن أو الفئة. من ناحية أخرى، سيتم توجيه طلب POST /cart/123
إلى طريقة post()
الخاصة بفئة Item
.
ملاحظة: لا تقوم المتصفحات بتنفيذ أساليب HTTP PUT
و DELETE
في نماذج HTML العادية. لا يمكن الوصول إلى هذه الأساليب وغيرها من أساليب ReST ( HEAD
و CONNECT
) إلا عبر استدعاءات AJAX للخادم.
إذا تلقى إطار العمل طلب HTTP لمسار يقوم بتعيين طريقة لم يتم تنفيذها بواسطة فئة (ربما ارتكبت خطأ في تعيين المسار، أو لم تتم كتابة الطريقة بعد)، فإنه يقوم بإنشاء HTTP 405 Method Not Allowed
خطأ HTTP 405 Method Not Allowed
.
إذا طلب العميل OPTIONS
HTTP لمورد URL، يستجيب F3 برؤوس HTTP المناسبة التي تشير إلى الطرق المسموح بها للمورد (HEAD، وGET، وPUT، وما إلى ذلك). لن يقوم الإطار بتعيين طلب OPTIONS
لفئة ما.
لدى Fat-Free طريقة لتحميل الفئات فقط في الوقت الذي تحتاج إليها، لذلك لا تستهلك ذاكرة أكبر مما يحتاجه جزء معين من تطبيقك. وليس عليك كتابة قائمة طويلة من عبارات include
أو require
فقط لتحميل فئات PHP المحفوظة في ملفات مختلفة ومواقع مختلفة. يمكن للإطار القيام بذلك تلقائيًا نيابةً عنك. ما عليك سوى حفظ ملفاتك (فئة واحدة لكل ملف) في مجلد وإخبار إطار العمل بتحميل الملف المناسب تلقائيًا بمجرد استدعاء طريقة في الفصل: -
$ f3 -> set ( ' AUTOLOAD ' , ' autoload/ ' );
يمكنك تعيين موقع مختلف للفصول التي تم تحميلها تلقائيًا عن طريق تغيير قيمة المتغير العام AUTOLOAD
. يمكنك أيضًا الحصول على مسارات تحميل تلقائي متعددة. إذا كانت فئاتك منظمة وفي مجلدات مختلفة، فيمكنك توجيه إطار العمل إلى التحميل التلقائي للفئة المناسبة عند استدعاء طريقة ثابتة أو عند إنشاء كائن. قم بتعديل متغير AUTOLOAD
بهذه الطريقة: -
$ f3 -> set ( ' AUTOLOAD ' , ' admin/autoload/; user/autoload/; default/ ' );
هام: باستثناء الامتداد .php، يجب أن يكون اسم الفئة واسم الملف متطابقين، حتى يتمكن إطار العمل من التحميل التلقائي لفصلك بشكل صحيح. يجب أن يكون الاسم الأساسي لهذا الملف مطابقًا لاستدعاء الفصل الدراسي الخاص بك، على سبيل المثال، سيبحث F3 إما عن Foo/BarBaz.php
أو foo/barbaz.php
عندما يكتشف عبارة new FooBarBaz
في تطبيقك.
يسمح AUTOLOAD
للتسلسلات الهرمية للفئة بالتواجد في مجلدات فرعية ذات أسماء مشابهة، لذلك إذا كنت تريد أن يقوم إطار العمل بالتحميل التلقائي لفئة ذات مساحة اسم يتم استدعاؤها بالطريقة التالية: -
$ f3 -> set ( ' AUTOLOAD ' , ' autoload/ ' );
$ obj = new Gadgets iPad ;
يمكنك إنشاء تسلسل هرمي للمجلدات يتبع نفس البنية. بافتراض أن /var/www/html/
هو جذر الويب الخاص بك، فسيبحث F3 عن الفئة في /var/www/html/autoload/gadgets/ipad.php
. يجب أن يحتوي الملف ipad.php
على الحد الأدنى من الكود التالي:-
namespace Gadgets ;
class iPad {}
تذكر: يجب أن تنتهي جميع أسماء الأدلة في Fat-Free بشرطة مائلة. يمكنك تعيين مسار بحث للمحمل التلقائي كما يلي:-
$ f3 -> set ( ' AUTOLOAD ' , ' main/;aux/ ' );
F3، كونه إطار عمل مدركًا لمساحة الاسم، يسمح لك باستخدام طريقة في فئة ذات مساحة اسم كمعالج مسار، وهناك عدة طرق للقيام بذلك. لاستدعاء طريقة ثابتة: -
$ f3 -> set ( ' AUTOLOAD ' , ' classes/ ' );
$ f3 -> route ( ' GET|POST / ' , ' MainHome::show ' );
سوف يستدعي الكود أعلاه طريقة show()
الثابتة للفئة Home
داخل مساحة الاسم Main
. يجب حفظ فئة Home
في المجلد classes/main/home.php
حتى يتم تحميلها تلقائيًا.
إذا كنت تفضل العمل مع الكائنات: -
$ f3 -> route ( ' GET|POST / ' , ' MainHome->show ' );
سيقوم بإنشاء مثيل للفئة Home
في وقت التشغيل واستدعاء طريقة show()
بعد ذلك.
يحتوي F3 على اثنين من مستمعي أحداث التوجيه التي قد تساعدك على تحسين تدفق فئات وحدات التحكم وبنيتها. لنفترض أن لديك طريقًا محددًا على النحو التالي: -
$ f3 -> route ( ' GET / ' , ' Main->home ' );
إذا تلقى التطبيق طلب HTTP يطابق المسار أعلاه، فسيقوم F3 بإنشاء مثيل Main
، ولكن قبل تنفيذ طريقة home()
، يبحث إطار العمل عن طريقة في هذه الفئة تسمى beforeRoute()
. في حالة العثور عليه، يقوم F3 بتشغيل التعليمات البرمجية الموجودة في معالج الأحداث beforeRoute()
قبل نقل التحكم إلى الأسلوب home()
. بمجرد إنجاز ذلك، يبحث إطار العمل عن معالج الأحداث afterRoute()
. مثل beforeRoute()
، يتم تنفيذ الطريقة إذا تم تعريفها.
إليك ميزة أخرى لـ F3: -
$ f3 -> route ( ' GET /products/@action ' , ' Products->@action ' );
إذا تلقى تطبيقك طلبًا، على سبيل المثال، /products/itemize
، فسيقوم F3 باستخراج سلسلة 'itemize'
من عنوان URL وتمريرها إلى الرمز المميز @action
في معالج المسار. سيبحث F3 بعد ذلك عن فئة تسمى Products
ويقوم بتنفيذ طريقة itemize()
.
قد يكون لمعالجات المسار الديناميكي أشكال مختلفة: -
// static method
$ f3 -> route ( ' GET /public/@genre ' , ' Main::@genre ' );
// object mode
$ f3 -> route ( ' GET /public/@controller/@action ' , ' @controller->@action ' );
يؤدي F3 إلى ظهور خطأ HTTP 404 Not Found
في وقت التشغيل إذا لم يتمكن من نقل التحكم إلى الفئة أو الطريقة المرتبطة بالمسار الحالي، أي فئة أو طريقة غير محددة.
قد تحتوي أنماط التوجيه على معدّلات توجه إطار العمل ليبني قرار التوجيه الخاص به على نوع طلب HTTP: -
$ f3 -> route ( ' GET /example [ajax] ' , ' Page->getFragment ' );
$ f3 -> route ( ' GET /example [sync] ' , ' Page->getFull ' );
ستقوم العبارة الأولى بتوجيه طلب HTTP إلى رد الاتصال Page->getFragment()
فقط في حالة استلام الخادم لرأس X-Requested-With: XMLHttpRequest
(كائن AJAX). إذا تم اكتشاف طلب عادي (متزامن)، فسوف ينزل F3 ببساطة إلى نمط المطابقة التالي، وفي هذه الحالة ينفذ رد الاتصال Page->getFull()
.
إذا لم يتم تحديد أي معدّلات في نمط التوجيه، فسيتم توجيه كل من أنواع الطلبات AJAX والمتزامنة إلى المعالج المحدد.
يتم التعرف أيضًا على معدّلات نمط المسار بواسطة $f3->map()
.
المتغيرات المحددة في Fat-Free هي متغيرات عالمية، أي يمكن الوصول إليها بواسطة أي مكون من مكونات MVC. لا تتطابق عوالم إطار العمل مع عوالم PHP. المتغير F3 المسمى content
ليس مطابقًا للمتغير $content
الخاص بـ PHP. F3 هي لغة خاصة بالمجال في حد ذاتها وتحتفظ بجدول رموز منفصل خاص بها لمتغيرات النظام والتطبيق. إطار العمل، مثل أي برنامج موجه للكائنات مصمم جيدًا، لا يلوث مساحة الاسم العامة لـ PHP بالثوابت أو المتغيرات أو الوظائف أو الفئات التي قد تتعارض مع أي تطبيق. على عكس أطر العمل الأخرى، لا يستخدم F3 بيان define()
الخاص بـ PHP. تقتصر جميع ثوابت الإطار على الفئات.
لتعيين قيمة لمتغير خالي من الدهون:
$ f3 -> set ( ' var ' ,value); // or
$ f3 -> var =value;
$ f3 -> set ( ' hello.world ' , ' good morning ' ); // translates to : 'hello' == array ( 'world' = > 'good morning' )
$ f3 ->{ ' hello.world ' }= ' good morning ' ; // same as prior statement
ملاحظة: تقبل المتغيرات Fat-Free جميع أنواع بيانات PHP، بما في ذلك الكائنات والوظائف المجهولة.
لتعيين عدة متغيرات في وقت واحد:
$ f3 -> mset (
[
' foo ' => ' bar ' ,
' baz ' => 123
]
);
لاسترداد قيمة متغير إطار العمل المسمى var
:-
echo $ f3 -> get ( ' var ' ); // or
echo $ f3 -> var ;
لإزالة متغير Fat-Free من الذاكرة إذا لم تعد بحاجة إليه (تخلص منه حتى لا يتداخل مع وظائفك/طرقك الأخرى)، استخدم الطريقة: -
$ f3 -> clear ( ' var ' ); // or
unset( $ f3 -> var );
لمعرفة ما إذا كان المتغير قد تم تعريفه مسبقًا: -
$ f3 -> exists ( ' var ' ) //
isset ( $ f3 -> var )
يحتفظ F3 بجدول الرموز الخاص به لمتغيرات إطار العمل والتطبيق، والتي تكون مستقلة عن PHP. يتم تعيين بعض المتغيرات إلى PHP globals. SESSION
Fat-Free تعادل $_SESSION
، و REQUEST
تقابل $_REQUEST
. يوصى باستخدام متغيرات إطار العمل، بدلاً من PHP، لمساعدتك في نقل البيانات عبر وظائف وفئات وأساليب مختلفة. كما أن لديهم مزايا أخرى:-
SESSION
إلى تغيير $_SESSION
الأساسي لـ PHP أيضًا. تغيير الأخير يغير أيضًا نظير الإطار. لا يحتفظ Fat-Free بمخزن غبي للمتغيرات وقيمها. يمكنه أيضًا أتمتة إدارة الجلسة وأشياء أخرى. يؤدي تعيين قيمة أو استردادها من خلال متغير SESSION
الخاص بـ F3 إلى بدء الجلسة تلقائيًا. إذا كنت تستخدم $_SESSION
(أو الوظائف المرتبطة بالجلسة) مباشرةً، فبدلاً من متغير إطار العمل SESSION
، يصبح تطبيقك مسؤولاً عن إدارة الجلسات.
كقاعدة عامة، لا تستمر متغيرات إطار العمل بين طلبات HTTP. فقط SESSION
و COOKIE
(وعناصرهما) التي تم تعيينها إلى متغيرات PHP $_SESSION
و $_COOKIE
العامة معفاة من طبيعة HTTP عديمة الحالة.
هناك العديد من المتغيرات العالمية المحددة مسبقًا المستخدمة داخليًا بواسطة Fat-Free، ويمكنك بالتأكيد الاستفادة منها في تطبيقك. تأكد من أنك تعرف ما تفعله. قد يؤدي تغيير بعض المتغيرات العالمية لـ Fat-Free إلى سلوك إطاري غير متوقع.
يحتوي إطار العمل على العديد من المتغيرات لمساعدتك في الحفاظ على تنظيم ملفاتك وهياكل الدليل. لقد رأينا كيف يمكننا أتمتة تحميل الفصل باستخدام AUTOLOAD
. يوجد متغير عام UI
، والذي يحتوي على المسار الذي يشير إلى موقع عروض/قوالب HTML الخاصة بك. DEBUG
هو متغير آخر ستستخدمه كثيرًا أثناء تطوير التطبيق ويتم استخدامه لتعيين إسهاب آثار الأخطاء.
ارجع إلى المرجع السريع إذا كنت بحاجة إلى قائمة شاملة لمتغيرات إطار العمل المضمنة.
قد يحتوي متغير الإطار على أي عدد من الأحرف والأرقام والشرطات السفلية. يجب أن يبدأ بحرف ألفا ويجب ألا يحتوي على مسافات. أسماء المتغيرات حساسة لحالة الأحرف.
يستخدم F3 الأحرف الكبيرة للمتغيرات العامة الداخلية المحددة مسبقًا. لا شيء يمنعك من استخدام أسماء المتغيرات التي تتكون من أحرف كبيرة في برنامجك الخاص، ولكن كقاعدة عامة، التزم بالأحرف الصغيرة (أو CamelCase) عند إعداد المتغيرات الخاصة بك حتى تتمكن من تجنب أي تعارض محتمل مع إصدارات إطار العمل الحالية والمستقبلية .
يجب ألا تستخدم كلمات PHP المحجوزة مثل if
و for
class
و default
وما إلى ذلك كأسماء لمتغيرات إطار العمل. هذه قد تسبب نتائج غير متوقعة.
يوفر F3 أيضًا عددًا من الأدوات لمساعدتك في التعامل مع متغيرات إطار العمل.
$ f3 -> set ( ' a ' , ' fire ' );
$ f3 -> concat ( ' a ' , ' cracker ' );
echo $ f3 -> get ( ' a ' ); // returns the string 'firecracker'
$ f3 -> copy ( ' a ' , ' b ' );
echo $ f3 -> get ( ' b ' ); // returns the same string : 'firecracker'
يوفر F3 أيضًا بعض الطرق البدائية للعمل مع متغيرات المصفوفة: -
$ f3 -> set ( ' colors ' ,[ ' red ' , ' blue ' , ' yellow ' ]);
$ f3 -> push ( ' colors ' , ' green ' ); // works like PHP ' s array_push ()
echo $ f3 -> pop ( ' colors ' ); // returns 'green'
$ f3 -> unshift ( ' colors ' , ' purple ' ); // similar to array_unshift ()
echo $ f3 -> shift ( ' colors ' ); // returns 'purple'
$ f3 -> set ( ' grays ' ,[ ' light ' , ' dark ' ]);
$ result = $ f3 -> merge ( ' colors ' , ' grays ' ); // merges the two arrays
على عكس الأطر الأخرى التي تحتوي على هياكل مجلدات صلبة، يمنحك F3 قدرًا كبيرًا من المرونة. يمكن أن يكون لديك بنية مجلد تبدو هكذا (تمثل الكلمات الموجودة بين قوسين بأحرف كبيرة متغيرات إطار عمل F3 التي تحتاج إلى التغيير والتبديل): -
/ (your Web root, where index.php is located)
app/ (application files)
dict/ (LOCALES, optional)
controllers/
logs/ (LOGS, optional)
models/
views/ (UI)
css/
js/
lib/ (you can store base.php here)
tmp/ (TEMP, used by the framework)
cache/ (CACHE)
لا تتردد في تنظيم الملفات والأدلة الخاصة بك بالطريقة التي تريدها. فقط قم بتعيين المتغيرات العالمية F3 المناسبة. إذا كنت تريد موقعًا آمنًا حقًا، فإن Fat-Free يسمح لك بتخزين جميع ملفاتك في دليل لا يمكن الوصول إليه عبر الويب. الشرط الوحيد هو أن تترك index.php
و .htaccess
وملفاتك العامة، مثل CSS وJavaScript والصور وما إلى ذلك، في مسار مرئي لمتصفحك.
يقوم Fat-Free بإنشاء صفحات أخطاء HTML الخاصة به، مع تتبعات مكدسة لمساعدتك في تصحيح الأخطاء. وهنا مثال:-
خطأ في الخادم الداخلي
تتوقع الدالة strpos() معلمتين على الأقل، مع إعطاء 0
• var/html/dev/main.php:96 strpos() • var/html/dev/index.php:16 Base->run()
إذا كنت تشعر أن الأمر بسيط جدًا أو ترغب في القيام بأشياء أخرى عند حدوث الخطأ، فيمكنك إنشاء معالج الأخطاء المخصص الخاص بك: -
$ f3 -> set ( ' ONERROR ' ,
function ( $ f3 ) {
// custom error handler code goes here
// use this if you want to display errors in a
// format consistent with your site ' s theme
echo $ f3 -> get ( ' ERROR.status ' );
}
);
يحتفظ F3 بمتغير عام يحتوي على تفاصيل الخطأ الأخير الذي حدث في التطبيق الخاص بك. المتغير ERROR
عبارة عن صفيف منظم على النحو التالي: -
ERROR.code - displays the error code (404, 500, etc.)
ERROR.status - header and page title
ERROR.text - error context
ERROR.trace - stack trace
أثناء تطوير التطبيق الخاص بك، من الأفضل تعيين مستوى التصحيح إلى الحد الأقصى حتى تتمكن من تتبع كافة الأخطاء إلى السبب الجذري لها: -
$ f3 -> set ( ' DEBUG ' , 3 );
ما عليك سوى إدخال الأمر في تسلسل تمهيد التطبيق الخاص بك.
بمجرد أن يصبح تطبيقك جاهزًا للإصدار، ما عليك سوى إزالة البيان من تطبيقك أو استبداله بما يلي: -
$ f3 -> set ( ' DEBUG ' , 0 );
سيؤدي هذا إلى منع إخراج تتبع المكدس في أي صفحة خطأ HTML تم إنشاؤها بواسطة النظام (لأنه ليس من المفترض أن يراها زوار موقعك).
يمكن أن يحتوي DEBUG
على قيم تتراوح من 0 (تم منع تتبع المكدس) إلى 3 (الأكثر تفصيلاً).
لا تنسى! قد تحتوي عمليات تتبع المكدس على مسارات وأسماء ملفات وأوامر قاعدة بيانات وأسماء مستخدمين وكلمات مرور. قد تعرض موقع الويب الخاص بك لمخاطر أمنية غير ضرورية إذا فشلت في تعيين المتغير العام DEBUG
إلى 0 في بيئة الإنتاج.
إذا كان التطبيق الخاص بك يحتاج إلى أن يكون قابلاً للتكوين من قبل المستخدم، فإن F3 يوفر طريقة سهلة لقراءة ملفات التكوين لإعداد التطبيق الخاص بك. بهذه الطريقة، يمكنك أنت والمستخدمون لديك تعديل التطبيق دون تغيير أي كود PHP.
بدلاً من إنشاء برنامج PHP النصي الذي يحتوي على نموذج التعليمات البرمجية التالي: -
$ f3 -> set ( ' num ' , 123 );
$ f3 -> set ( ' str ' , ' abc ' );
$ f3 -> set ( ' hash ' ,[ ' x ' => 1 , ' y ' => 2 , ' z ' => 3 ]);
$ f3 -> set ( ' items ' ,[ 7 , 8 , 9 ]);
$ f3 -> set ( ' mix ' ,[ ' this ' , 123.45 , FALSE ]);
يمكنك إنشاء ملف تكوين يقوم بنفس الشيء: -
[globals]
num =123
; this is a regular string
str =abc
; another way of assigning strings
str = " abc "
; this is an array
hash[x]=1
hash[y]=2
hash[z]=3
; dot-notation is recognized too
hash.x =1
hash.y =2
hash.z =3
; this is also an array
items =7,8,9
; array with mixed elements
mix = " this " ,123.45,FALSE
بدلاً من عبارات $f3->set()
الطويلة في التعليمات البرمجية الخاصة بك، يمكنك توجيه إطار العمل لتحميل ملف تكوين كبديل للتعليمات البرمجية. دعونا نحفظ النص أعلاه كـ setup.cfg. يمكننا بعد ذلك أن نسميها بطريقة بسيطة: -
$ f3 -> config ( ' setup.cfg ' );
ليس من الضروري أن يتم اقتباس قيم السلسلة، إلا إذا كنت تريد تضمين مسافات بادئة أو لاحقة. إذا كان يجب التعامل مع الفاصلة كجزء من سلسلة، فقم بإحاطة السلسلة باستخدام علامات الاقتباس المزدوجة - وإلا فسيتم التعامل مع القيمة كمصفوفة (يتم استخدام الفاصلة كفاصل لعناصر المصفوفة). يمكن أن تمتد السلاسل على عدة أسطر: -
[globals]
str = " this is a
very long
string "
يمنحك F3 أيضًا القدرة على تحديد مسارات HTTP في ملفات التكوين: -
[routes]
GET /=home
GET / 404 =App->page404
GET /page/@ num =Page->@controller
يمكن تعريف خرائط الطريق في ملفات التكوين أيضًا: -
[maps]
/ blog =BlogLogin
/blog/@ controller =Blog@controller
رؤوس الأقسام [globals]
و [routes]
و [maps]
مطلوبة. يمكنك دمج كلا القسمين في ملف تكوين واحد - على الرغم من أنه يوصى بوجود [routes]
و [maps]
في ملف منفصل. بهذه الطريقة يمكنك السماح للمستخدمين النهائيين بتعديل بعض العلامات الخاصة بالتطبيقات، وفي الوقت نفسه منعهم من التدخل في منطق التوجيه الخاص بك.
يجب أن تكون واجهة المستخدم مثل صفحة HTML مستقلة عن كود PHP الأساسي المتعلق بالتوجيه ومنطق الأعمال. وهذا أمر أساسي لنموذج MVC. يجب ألا تتطلب المراجعة الأساسية مثل تحويل <h3>
إلى <p>
تغييرًا في كود التطبيق الخاص بك. بنفس الطريقة، تحويل مسار بسيط مثل GET /about
إلى GET /about-us
يجب ألا يكون له أي تأثير على واجهة المستخدم الخاصة بك ومنطق العمل (العرض والنموذج في MVC، أو التمثيل والأسلوب في RMR).
خلط بنيات البرمجة ومكونات واجهة المستخدم في ملف واحد ، مثل ترميز السباغيتي ، يجعل صيانة التطبيق في المستقبل كابوسًا.
F3 يدعم PHP كمحرك قالب. ألقِ نظرة على جزء HTML المحفوظ كـ template.htm
:-.
< p > Hello, < ?php echo $name; ? > ! </ p >
إذا تم تمكين العلامات القصيرة على الخادم الخاص بك ، فيجب أن يعمل هذا أيضًا:-
< p > Hello, < ?= $name ? > </ p >
لعرض هذا القالب ، يمكنك الحصول على رمز PHP الذي يبدو مثل هذا (مخزّن في ملف منفصل عن القالب):-
$ f3 = require ( ' lib/base.php ' );
$ f3 -> route ( ' GET / ' ,
function ( $ f3 ) {
$ f3 -> set ( ' name ' , ' world ' );
$ view = new View ;
echo $ view -> render ( ' template.htm ' );
// Previous two lines can be shortened to : -
// echo View :: instance () - > render ( 'template.htm' );
}
);
$ f3 -> run ();
المشكلة الوحيدة في استخدام PHP كمحرك قالب ، بسبب رمز PHP المضمن في هذه الملفات ، هي الجهد الواعي اللازم للالتزام بالإرشادات حول فصل المخاوف ومقاومة إغراء مزج منطق الأعمال مع واجهة المستخدم الخاصة بك.
كبديل لـ PHP ، يمكنك استخدام محرك القالب الخاص بـ F3. يمكن إعادة كتابة جزء HTML أعلاه على النحو التالي:-
< p > Hello, {{ @name }}! </ p >
والرمز اللازم لعرض هذا القالب:-
$ f3 = require ( ' lib/base.php ' );
$ f3 -> route ( ' GET / ' ,
function ( $ f3 ) {
$ f3 -> set ( ' name ' , ' world ' );
$ template = new Template ;
echo $ template -> render ( ' template.htm ' );
// Above lines can be written as : -
// echo Template :: instance () - > render ( 'template.htm' );
}
);
$ f3 -> run ();
مثل التوجيه الرموز المستخدمة في اللحاق بالمتغيرات في عناوين URL (لا تزال تذكر مثال GET /brew/@count
في القسم السابق؟) ، تبدأ رموز قالب F3 برمز @
متبوعًا بسلسلة من الرسائل والأرقام المحاطة بأقواس مجعدة. يجب أن تكون الشخصية الأولى ألفا. تحتوي الرموز المميزة على مراسلات فردية مع متغيرات إطار. يستبدل الإطار تلقائيًا رمزًا بالقيمة المخزنة في متغير يحمل نفس الاسم.
في مثالنا ، يحل F3 محل رمز @name
في قالبنا بالقيمة التي قمنا بتعيينها لمتغير الاسم. في وقت التشغيل ، سيكون إخراج الرمز أعلاه:-
< p > Hello, world </ p >
هل أنت قلق بشأن أداء قوالب F3؟ في وقت التشغيل ، يقوم الإطار بتحليل وتجميع/يحول قالب F3 إلى رمز PHP لأول مرة يتم عرضه عبر $template->render()
. ثم يستخدم الإطار هذا الرمز المترجم في جميع المكالمات اللاحقة. وبالتالي ، يجب أن يكون الأداء هو نفسه قوالب PHP ، إن لم يكن أفضل بسبب تحسين الكود الذي يقوم به برنامج التحويل البرمجي عندما يتم إشراك قوالب أكثر تعقيدًا.
سواء كنت تستخدم محرك قالب PHP أو F3 الخاص ، يمكن أن يكون عرض القالب أسرع بكثير إذا كان لديك APC أو WinCache أو XCache على الخادم الخاص بك.
كما ذكرنا سابقًا ، يمكن للمتغيرات الإطارية الاحتفاظ بأي نوع من بيانات PHP. ومع ذلك ، قد يؤدي استخدام أنواع البيانات غير المقيدة في قوالب F3 إلى نتائج غريبة إذا لم تكن حريصًا. سيتم دائمًا تقييم التعبيرات في أقواس مجعد وتحويلها إلى سلسلة. يجب عليك الحد من متغيرات واجهة المستخدم الخاصة بك إلى عدد البيانات البسيطة:- string
، integer
، boolean
أو float
.
لكن ماذا عن المصفوفات؟ يتعرف على المصفوفات الخالية من الدهون ويمكنك توظيفها في القوالب الخاصة بك. يمكنك الحصول على شيء مثل:-
< p > {{ @buddy[0] }}, {{ @buddy[1] }}, and {{ @buddy[2] }} </ p >
وملء صفيف @buddy
في رمز PHP الخاص بك قبل تقديم القالب:-
$ f3 -> set ( ' buddy ' ,[ ' Tom ' , ' Dick ' , ' Harry ' ]);
ومع ذلك ، إذا قمت ببساطة بإدراج {{ @buddy }}
في القالب الخاص بك ، فسيقوم PHP باستبداله بـ 'Array'
لأنه يحول الرمز المميز إلى سلسلة. PHP ، من ناحية أخرى ، ستقوم بإنشاء Array to string conversion
في وقت التشغيل.
يسمح لك F3 بتضمين التعبيرات في القوالب. قد تتخذ هذه التعبيرات أشكالًا مختلفة ، مثل الحسابات الحسابية ، والتعبيرات المنطقية ، وثوابت PHP ، وما إلى ذلك. فيما يلي بعض الأمثلة:-
{{ 2*(@page-1) }}
{{ (int)765.29+1.2e3 }}
< option value =" F " {{ @active? 'selected=" selected "':'' }} > Female </ option >
{{ var_dump(@xyz) }}
< p > That is {{ preg_match('/Yes/i',@response)?'correct':'wrong' }}! </ p >
{{ @obj- > property }}
ملاحظة إضافية حول تعبيرات الصفيف: لاحظ أن @foo.@bar
عبارة عن سلسلة متسلقة $foo.$bar
) ، في حين أن @foo.bar
يترجم إلى $foo['bar']
. إذا كان $foo[$bar]
هو ما تقصده ، فاستخدم @foo[@bar]
تدوين منتظم.
قد تحتوي المتغيرات الإطارية أيضًا على وظائف مجهولة:
$ f3 -> set ( ' func ' ,
function ( $ a , $ b ) {
return $ a . ' , ' . $ b ;
}
);
سيقوم محرك قالب F3 بتفسير الرمز المميز كما هو متوقع ، إذا حددت التعبير التالي:
{{ @func('hello','world') }}
الاستبدال المتغير البسيط هو شيء واحد لديها محركات القالب. خالية من الدهون لديها المزيد من الأكمام:-
< include href =" header.htm " />
سيقوم التوجيه بتضمين محتويات قالب header.htm في الموضع الدقيق حيث يتم ذكر التوجيه. يمكنك أيضًا الحصول على محتوى ديناميكي في شكل:-
< include href =" {{ @content }} " />
الاستخدام العملي لهذا التوجيه القالب هو عندما يكون لديك عدة صفحات مع تخطيط HTML شائع ولكن مع محتوى مختلف. إن توجيه الإطار لإدراج عائلي فرعي في القالب الرئيسي الخاص بك أمر بسيط مثل كتابة رمز PHP التالي:-
// switch content to your blog sub - template
$ f3 -> set ( ' content ' , ' blog.htm ' );
// in another route , switch content to the wiki sub - template
$ f3 -> set ( ' content ' , ' wiki.htm ' );
قد يحتوي العائد الفرعي بدوره على أي عدد من التوجيهات. F3 يسمح قوالب متداخلة غير محدودة.
يمكنك تحديد أسماء الملفات بشيء آخر غير امتدادات ملف .htm أو .html ، ولكن من الأسهل معاينتها في متصفح الويب الخاص بك أثناء مرحلة التطوير والتصحيح. لا يقتصر محرك القالب على تقديم ملفات HTML. في الواقع ، يمكنك استخدام محرك القالب لتقديم أنواع أخرى من الملفات.
يحتوي التوجيه <include>
أيضًا على سمة اختيارية if
يمكنك تحديد شرط يجب أن يتم استيفاءه قبل إدراج العائل الفرعي:-
< include if =" {{ count(@items) }} " href =" items.htm " />
أثناء كتابة/تصحيح البرامج التي تعمل بتصميم F3 وقوالب تصميم ، قد تكون هناك حالات قد تكون فيها تعطيل عرض كتلة من HTML. يمكنك استخدام التوجيه <exclude>
لهذا الغرض:-
< exclude >
< p > A chunk of HTML we don't want displayed at the moment </ p >
</ exclude >
هذا مثل علامة التعليقات <!-- comment -->
html ، لكن التوجيه <exclude>
يجعل كتلة HTML غير مرئية تمامًا بمجرد تقديم القالب.
إليك طريقة أخرى لاستبعاد محتوى القالب أو إضافة تعليقات:-
{* < p > A chunk of HTML we don't want displayed at the moment </ p > *}
ميزة قالب مفيدة أخرى هي <check>
التوجيه. يسمح لك بتضمين جزء HTML اعتمادًا على تقييم حالة معينة. فيما يلي بعض الأمثلة:-
< check if =" {{ @page=='Home' }} " >
< false > < span > Inserted if condition is false </ span > </ false >
</ check >
< check if =" {{ @gender=='M' }} " >
< true >
< div > Appears when condition is true </ div >
</ true >
< false >
< div > Appears when condition is false </ div >
</ false >
</ check >
يمكنك الحصول على أكبر عدد من التوجيهات المتداخلة <check>
كما تحتاج.
تعبير F3 داخل سمة if تساوي NULL
، سلسلة فارغة ، FALSE
منطقي ، صفيف فارغ أو صفر ، يستدعي تلقائيًا <false>
. إذا كان القالب الخاص بك لا يحتوي على <false>
كتلة ، فإن علامات الفتح والإغلاق <true>
اختيارية:---
< check if =" {{ @loggedin }} " >
< p > HTML chunk to be included if condition is true </ p >
</ check >
يمكن أن تعالج خالية من الدهون أيضًا كتل HTML المتكررة:-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " >
< p > {{ trim(@fruit) }} </ p >
</ repeat >
يجب أن تكون سمة group
@fruits
داخل توجيه <repeat>
صفيفًا ويجب تعيينها في رمز PHP وفقًا لذلك:-
$ f3 -> set ( ' fruits ' ,[ ' apple ' , ' orange ' , ' banana ' ]);
لم يتم الحصول على أي شيء عن طريق تعيين قيمة إلى @fruit
في رمز التطبيق الخاص بك. يتجاهل FREE FREE أي قيمة محددة مسبقًا قد يكون لها لأنه يستخدم المتغير لتمثيل العنصر الحالي أثناء التكرار على المجموعة. يصبح إخراج جزء قالب HTML أعلاه ورمز PHP المقابل:-
< p > apple </ p >
< p > orange </ p >
< p > banana </ p >
يتيح الإطار تعشيشًا غير محدود من الكتل <repeat>
:-
< repeat group =" {{ @div }} " key =" {{ @ikey }} " value =" {{ @idiv }} " >
< div >
< p > < span > < b > {{ @ikey }} </ b > </ span > </ p >
< p >
< repeat group =" {{ @idiv }} " value =" {{ @ispan }} " >
< span > {{ @ispan }} </ span >
</ repeat >
</ p >
</ div >
</ repeat >
قم بتطبيق أمر F3 التالي:-
$ f3 -> set ( ' div ' ,
[
' coffee ' =>[ ' arabica ' , ' barako ' , ' liberica ' , ' kopiluwak ' ],
' tea ' =>[ ' darjeeling ' , ' pekoe ' , ' samovar ' ]
]
);
نتيجة لذلك ، تحصل على جزء HTML التالي:-
< div >
< p > < span > < b > coffee </ b > </ span > </ p >
< p >
< span > arabica </ span >
< span > barako </ span >
< span > liberica </ span >
< span > kopiluwak </ span >
< p >
</ div >
< div >
< p > < span > < b > tea </ b > </ span > </ p >
< p >
< span > darjeeling </ span >
< span > pekoe </ span >
< span > samovar </ span >
</ p >
</ div >
مذهل ، أليس كذلك؟ والشيء الوحيد الذي كان عليك القيام به في PHP هو تحديد محتويات div
متغير F3 واحد لاستبدال رمز الرمز @div
. يجعل الدهون خالية من الدهون كل من تصميم برمجة ومواقع الويب سهلة للغاية.
تقوم سمة value
Template Template <repeat>
بإرجاع قيمة العنصر الحالي في التكرار. إذا كنت بحاجة إلى الحصول على مفتاح الصفيف للعنصر الحالي ، فاستخدم سمة key
بدلاً من ذلك. السمة key
اختيارية.
<repeat>
يحتوي أيضًا على سمة مضادة اختيارية يمكن استخدامها على النحو التالي:-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " counter =" {{ @ctr }} " >
< p class =" {{ @ctr%2?'odd':'even' }} " > {{ trim(@fruit) }} </ p >
</ repeat >
داخليًا ، يسجل محرك قالب F3 عدد تكرارات الحلقة ويحفظ تلك القيمة في المتغير/الرمز @ctr
، والذي يتم استخدامه في مثالنا لتحديد التصنيف الفردي/حتى.
إذا كان عليك إدراج الرموز الرموز F3 داخل قسم <script>
أو <style>
من القالب الخاص بك ، فسيظل الإطار يحل محلها بالطريقة المعتادة:-
< script type =" text/javascript " >
function notify ( ) {
alert ( 'You are logged in as: {{ @userID }}' ) ;
}
</ script >
لا تتطلب توجيهات قالب التضمين داخل <script>
أو <style>
العلامات الخاصة بك معالجة خاصة:-
< script type =" text/javascript " >
var discounts = [ ] ;
< repeat group = "{{ @rates }}" value = "{{ @rate }}" >
// whatever you want to repeat in Javascript, e.g.
discounts.push(" { { @ rate } } ");
</ repeat >
</ script >
بشكل افتراضي ، يستخدم Free Free مجموعة أحرف UTF-8 ما لم يتم تغييرها. يمكنك تجاوز هذا السلوك عن طريق إصدار شيء مثل:-
$ f3 -> set ( ' ENCODING ' , ' ISO-8859-1 ' );
بمجرد إبلاغ إطار مجموعة الأحرف المطلوبة ، ستستخدمها F3 في جميع قوالب HTML و XML حتى يتم تغييرها مرة أخرى.
كما ذكرنا سابقًا في هذا القسم ، لا يقتصر الإطار على قوالب HTML. يمكنك معالجة قوالب XML أيضًا. الميكانيكا متشابهة إلى حد كبير. لا يزال لديك نفس {{ @variable }}
و {{ expression }}
الرموز الرموز ، <repeat>
، <check>
، <include>
، و <exclude>
التوجيهات المتاحة الخاصة بك. فقط أخبر F3 أنك تمرر ملف XML بدلاً من HTML:-
echo Template:: instance ()-> render ( ' template.xml ' , ' application/xml ' );
تمثل الحجة الثانية نوع MIME للوثيقة التي يتم تقديمها.
يغطي مكون العرض في MVC كل ما لا يندرج تحت النموذج ووحدة التحكم ، مما يعني أن العرض التقديمي الخاص بك يمكن أن يتضمن ويجب أن يتضمن جميع أنواع واجهات المستخدم ، مثل RSS ، البريد الإلكتروني ، RDF ، FOAF ، الملفات النصية ، إلخ. يوضح لك أدناه كيفية فصل العرض التقديمي للبريد الإلكتروني عن منطق أعمال التطبيق الخاص بك:-
MIME-Version: 1.0
Content-type: text/html; charset={{ @ENCODING }}
From: {{ @from }}
To: {{ @to }}
Subject: {{ @subject }}
< p > Welcome, and thanks for joining {{ @site }}! </ p >
احفظ قالب البريد الإلكتروني أعلاه كـ Welcome.txt. سيكون رمز F3 المرتبط هو:-
$ f3 -> set ( ' from ' , ' <[email protected]> ' );
$ f3 -> set ( ' to ' , ' <[email protected]> ' );
$ f3 -> set ( ' subject ' , ' Welcome ' );
ini_set ( ' sendmail_from ' , $ f3 -> get ( ' from ' ));
mail (
$ f3 -> get ( ' to ' ),
$ f3 -> get ( ' subject ' ),
Template:: instance ()-> render ( ' email.txt ' , ' text/html ' )
);
نصيحة: استبدل وظيفة SMTP Mail () بـ IMAP_MAIL () إذا كان البرنامج النصي الخاص بك يتواصل مع خادم IMAP.
الآن أليس هذا شيئًا؟ بالطبع ، إذا كان لديك حزمة من مستلمي البريد الإلكتروني ، فستستخدم قاعدة بيانات لإلغاء الاسم الأول واسم العائلة والبريد الإلكتروني.
إليك حل بديل باستخدام المكون الإضافي SMTP F3:-
$ mail = new SMTP ( ' smtp.gmail.com ' , 465 , ' SSL ' , ' [email protected] ' , ' secret ' );
$ mail -> set ( ' from ' , ' <[email protected]> ' );
$ mail -> set ( ' to ' , ' "Slasher" <[email protected]> ' );
$ mail -> set ( ' subject ' , ' Welcome ' );
$ mail -> send (Template:: instance ()-> render ( ' email.txt ' ));
يدعم F3 لغات متعددة مباشرة خارج الصندوق.
أولاً ، قم بإنشاء ملف قاموس بالهيكل التالي (ملف واحد لكل لغة):-
<?php
return [
' love ' => ' I love F3 ' ,
' today ' => ' Today is {0,date} ' ,
' pi ' => ' {0,number} ' ,
' money ' => ' Amount remaining: {0,number,currency} '
];
احفظه dict/en.php
. دعنا ننشئ قاموسًا آخر ، هذه المرة للألمانية. احفظ الملف dict/de.php
:-
<?php
return [
' love ' => ' Ich liebe F3 ' ,
' today ' => ' Heute ist {0,date} ' ,
' money ' => ' Restbetrag: {0,number,currency} '
];
القواميس ليست أكثر من أزواج القيمة الرئيسية. يقوم F3 تلقائيًا بتركيب متغيرات الإطار بناءً على المفاتيح في ملفات اللغة. على هذا النحو ، من السهل تضمين هذه المتغيرات كرموز في القوالب الخاصة بك. باستخدام محرك قالب F3:-
< h1 > {{ @love }} </ h1 >
< p >
{{ @today,time() | format }}. < br />
{{ @money,365.25 | format }} < br />
{{ @pi }}
</ p >
والنسخة الأطول التي تستخدم PHP كمحرك قالب:-
<?php $ f3 =Base:: instance (); ?>
<h1> <?php echo $ f3 -> get ( ' love ' ); ?> </h1>
<p>
<?php echo $ f3 -> get ( ' today ' , time ()); ?> .<br />
<?php echo $ f3 -> get ( ' money ' , 365.25 ); ?>
<?php echo $ f3 -> get ( ' pi ' ); ?>
</p>
بعد ذلك ، نوجه F3 للبحث عن قواميس في dict/
المجلد:-
$ f3 -> set ( ' LOCALES ' , ' dict/ ' );
ولكن كيف يحدد الإطار أي لغة يجب استخدامها؟ ستكتشف F3 ذلك تلقائيًا من خلال النظر إلى رؤوس طلب HTTP أولاً ، وتحديداً رأس Accept-Language
الذي أرسله المتصفح.
لتجاوز هذا السلوك ، يمكنك تشغيل F3 لاستخدام لغة محددة من قبل المستخدم أو التطبيق:-
$ f3 -> set ( ' LANGUAGE ' , ' de ' );
ملاحظة: في المثال أعلاه ، يوجد مفتاح PI فقط في القاموس الإنجليزي. سيستخدم الإطار دائمًا اللغة الإنجليزية ( en
) كاحتياطي لإلغاء مفاتيح غير موجودة في اللغة المحددة (أو المكتشفة).
يمكنك أيضًا إنشاء ملفات القاموس لمتغيرات اللغة مثل en-US
و es-AR
، إلخ. في هذه الحالة ، سوف يستخدم F3 متغير اللغة أولاً (مثل es-AR
). إذا كانت هناك مفاتيح غير موجودة في البديل ، فسيبحث الإطار عن المفتاح بلغة الجذر ( es
) ، ثم استخدم ملف اللغة en
كأعود نهائي. تصبح أزواج قيمة القاموس مفتاح متغيرات F3 بمجرد الإشارة إليها. تأكد من عدم تعارض المفاتيح مع أي متغير إطار تم إنشاء مثيل له عبر $f3->set()
أو $f3->mset()
أو $f3->config()
.
هل لاحظت أن نمط 'Today is {0,date}'
في مثالنا السابق؟ تتوقف إمكانية F3 المتعددة اللغات على قواعد تنسيق السلسلة/الرسائل لمشروع وحدة العناية المركزة. يستخدم Framework مجموعة فرعية خاصة به من تنسيق سلسلة وحدة العناية المركزة. ليست هناك حاجة لتفعيل امتداد intl
من PHP على الخادم.
شيء آخر: يمكن أيضًا تحميل F3.
love = " I love F3 "
today = " Today is {0,date} "
pi = " {0,number} "
money = " Amount remaining: {0,number,currency} "
احفظه كـ dict/en.ini
حتى يتمكن الإطار من تحميله تلقائيًا.
بشكل افتراضي ، يهرب كل من معالج العرض ومحرك القالب من جميع المتغيرات المقدمة ، أي تم تحويله إلى كيانات HTML لحمايتك من هجمات حقن XSS الممكنة. من ناحية أخرى ، إذا كنت ترغب في تمرير شظايا HTML صالحة من رمز التطبيق الخاص بك إلى القالب الخاص بك:-
$ f3 -> set ( ' ESCAPE ' , FALSE );
قد يكون لهذا آثار غير مرغوب فيها. قد لا ترغب في أن تمر جميع المتغيرات عبر بلا هوادة. يتيح لك الخالية من الدهون أن يلفت المتغيرات بشكل فردي. لقوالب F3:-
{{ @html_content | raw }}
في حالة قوالب PHP:-
<?php echo View:: instance ()-> raw ( $ html_content ); ?>
كإضافة إلى الإرشاد التلقائي لمتغيرات F3 ، يمنحك الإطار أيضًا يد حرة في تعقيم مدخلات المستخدم من نماذج HTML:-
$ f3 -> scrub ( $ _GET , ' p; br; span; div; a ' );
سيؤدي هذا الأمر إلى تجريد جميع العلامات (باستثناء تلك المحددة في الوسيطة الثانية) والأحرف غير الآمنة من المتغير المحدد. إذا كان المتغير يحتوي على صفيف ، يتم تطهير كل عنصر في الصفيف بشكل متكرر. إذا تم تمرير علامة النجمة (*) كوسيطة ثانية ، يسمح $f3->scrub()
بجميع علامات HTML للمرور من خلال أحرف التحكم غير الآمنة.
تم تصميم FURE FREE لجعل وظيفة التواصل مع قواعد بيانات SQL نسيمًا. إذا لم تكن من النوع الذي تغمر نفسك في التفاصيل حول SQL ، ولكن تميل أكثر نحو معالجة البيانات الموجهة للكائنات ، يمكنك الانتقال مباشرة إلى القسم التالي من هذا البرنامج التعليمي. ومع ذلك ، إذا كنت بحاجة إلى القيام ببعض مهام تعامل البيانات المعقدة وأداء قاعدة البيانات ، فإن SQL هو الطريق للذهاب.
يتم إنشاء اتصال مع محرك SQL مثل MySQL و SQLite و SQL Server و Sybase و Oracle باستخدام الأمر المألوف $f3->set()
. سيكون الاتصال بقاعدة بيانات SQLite:-
$ db = new DB SQL ( ' sqlite:/absolute/path/to/your/database.sqlite ' );
مثال آخر ، هذه المرة مع MySQL:-
$ db = new DB SQL (
' mysql:host=localhost;port=3306;dbname=mysqldb ' ,
' admin ' ,
' p455w0rD '
);
نعم. كان ذلك سهلاً ، أليس كذلك؟ هذا إلى حد كبير كيف ستفعل نفس الشيء في PHP العادي. تحتاج فقط إلى معرفة تنسيق DSN لقاعدة البيانات التي تتصل بها. انظر قسم PDO في دليل PHP.
دعنا نستمر في رمز PHP الخاص بنا:-
$ f3 -> set ( ' result ' , $ db -> exec ( ' SELECT brandName FROM wherever ' ));
echo Template:: instance ()-> render ( ' abc.htm ' );
هاه ، ماذا يحدث هنا؟ ألا ينبغي لنا إعداد أشياء مثل PDOs والبيانات والمؤشرات وما إلى ذلك؟ الجواب البسيط هو: ليس عليك ذلك. يقوم F3 بتبسيط كل شيء من خلال رعاية كل العمل الشاق في الواجهة الخلفية.
هذه المرة نقوم بإنشاء قالب HTML مثل abc.htm
الذي يحتوي على ما يلي على الأقل:-
< repeat group =" {{ @result }} " value =" {{ @item }} " >
< span > {{ @item.brandName }} </ span >
</ repeat >
في معظم الحالات ، يجب أن تكون مجموعة الأوامر SQL كافية لإنشاء نتيجة جاهزة للويب حتى تتمكن من استخدام متغير صفيف result
في القالب الخاص بك مباشرة. سواء كان ذلك ، لن يمنعك خالية من الدهون من الدخول في معالج SQL الداخلي. في الواقع ، تستمد فئة DBSQL
الخاصة بـ F3 مباشرة من فئة PDO
الخاصة بـ PHP ، لذلك لا يزال بإمكانك الوصول إلى مكونات PDO الأساسية المتضمنة في كل عملية ، إذا كنت بحاجة إلى بعض التحكم في الحبوب الدقيقة.
هذا مثال آخر. بدلاً من بيان واحد يتم تقديمه كوسيطة لأمر $db->exec()
، يمكنك أيضًا تمرير مجموعة من عبارات SQL:-
$ db -> exec (
[
' DELETE FROM diet WHERE food="cola" ' ,
' INSERT INTO diet (food) VALUES ("carrot") ' ,
' SELECT * FROM diet '
]
);
F3 ذكي بما يكفي لمعرفة أنه إذا كنت تمر مجموعة من تعليمات SQL ، فإن هذا يشير إلى معاملة دفعة SQL. لا داعي للقلق بشأن تراجعات SQL وترتكب لأن الإطار سيعود تلقائيًا إلى الحالة الأولية لقاعدة البيانات في حالة حدوث أي خطأ أثناء المعاملة. إذا نجحت ، فإن F3 يرتكب جميع التغييرات التي تم إجراؤها على قاعدة البيانات.
يمكنك أيضًا البدء وإنهاء معاملة برمجيًا:-
$ db -> begin ();
$ db -> exec ( ' DELETE FROM diet WHERE food="cola" ' );
$ db -> exec ( ' INSERT INTO diet (food) VALUES ("carrot") ' );
$ db -> exec ( ' SELECT * FROM diet ' );
$ db -> commit ();
سيحدث التراجع إذا واجه أي من العبارات خطأ.
للحصول على قائمة بجميع إرشادات قاعدة البيانات الصادرة:-
echo $ db -> log ();
تمرير وسائط السلسلة إلى عبارات SQL محفوفة بالمخاطر. النظر في هذا:-
$ db -> exec (
' SELECT * FROM users ' .
' WHERE username=" ' . $ f3 -> get ( ' POST.userID ' . ' " ' )
);
إذا لم يمر جهاز POST
Variable userID
من خلال أي عملية للصرف الصحي للبيانات ، فيمكن للمستخدم الضار تمرير السلسلة التالية وتلف قاعدة البيانات الخاصة بك بشكل لا رجعة فيه:-
admin " ; DELETE FROM users; SELECT " 1
لحسن الحظ ، تساعدك الاستعلامات المعلمة على تخفيف هذه المخاطر:-
$ db -> exec (
' SELECT * FROM users WHERE userID=? ' ,
$ f3 -> get ( ' POST.userID ' )
);
إذا اكتشف F3 أن قيمة معلمة الاستعلام/الرمز المميز هي سلسلة ، فإن طبقة الوصول إلى البيانات الأساسية تفلت من السلسلة وتضيف علامات الاقتباس حسب الضرورة.
سيكون مثالنا في القسم السابق أكثر أمانًا من حقن SQL إذا كتب بهذه الطريقة:-
$ db -> exec (
[
' DELETE FROM diet WHERE food=:name ' ,
' INSERT INTO diet (food) VALUES (?) ' ,
' SELECT * FROM diet '
],
[
array ( ' :name ' => ' cola ' ),
array ( 1 => ' carrot ' ),
NULL
]
);
F3 مليء بمحطة (ORMS) التي سهلة الاستخدام (ORMS) التي تجلس بين تطبيقك وبياناتك-مما يجعله أسهل بكثير وأسرع لك أن تكتب برامج تتعامل مع عمليات البيانات الشائعة-مثل إنشاء ، استرداد ، تحديث ، وحذف معلومات (CRUD) من قواعد بيانات SQL و NOSQL. تقوم محركات البيانات بمعظم العمل عن طريق تعيين تفاعلات كائن PHP إلى استعلامات الواجهة الخلفية المقابلة.
لنفترض أن لديك قاعدة بيانات MySQL موجودة تحتوي على جدول لمستخدمي التطبيق الخاص بك. (SQLite ، PostgreSQL ، SQL Server ، Sybase سيفعل ذلك أيضًا.) كان سيتم إنشاؤه باستخدام أمر SQL التالي:-
CREATE TABLE users (
userID VARCHAR ( 30 ),
password VARCHAR ( 30 ),
visits INT ,
PRIMARY KEY (userID)
);
ملاحظة: MongoDB هو محرك قاعدة بيانات NOSQL ومخطط بطبيعته. يحتوي F3 على تطبيق NOSQL سريع الخفيف وخفيف الوزن يسمى JIG ، والذي يستخدم ملفات مسطحة php-serialized أو JSON المشفرة. لا تتطلب طبقات التجريد هذه هياكل بيانات صلبة. قد تختلف الحقول من سجل إلى آخر. يمكن أيضًا تعريفها أو إسقاطها أثناء الطيران.
الآن العودة إلى SQL. أولاً ، ننشئ التواصل مع قاعدة البيانات الخاصة بنا.
$ db = new DB SQL (
' mysql:host=localhost;port=3306;dbname=mysqldb ' ,
' admin ' ,
' wh4t3v3r '
);
لاسترداد سجل من جدولنا:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? ' , ' tarzan ' ]);
يقوم السطر الأول بتأسيس كائن Mapper Data الذي يتفاعل مع جدول users
في قاعدة البيانات الخاصة بنا. خلف المشهد ، يسترجع F3 بنية جدول users
ويحدد الحقل (الحقل) الذي يتم تعريفه على أنه مفتاح (مفتاح) أساسي. في هذه المرحلة ، لا يحتوي كائن Mapper على أي بيانات حتى الآن (الحالة الجافة) ، لذا $user
ليس أكثر من كائن منظم - لكنه يحتوي على الطرق التي يحتاجها لأداء عمليات CRUD الأساسية وبعض الإضافات. لاسترداد سجل من جدول المستخدمين لدينا مع حقل userID
الذي يحتوي على قيمة السلسلة tarzan
، نستخدم load() method
. تسمى هذه العملية "التلقائي التلقائي" كائن Mapper Data.
سهل ، أليس كذلك؟ يدرك F3 أن جدول SQL لديه بالفعل تعريف هيكلي موجود داخل محرك قاعدة البيانات نفسه. على عكس الأطر الأخرى ، لا يتطلب F3 أي إعلانات فئة إضافية (إلا إذا كنت ترغب في توسيع نطاق محركات البيانات لتناسب الكائنات المعقدة) ، لا يوجد مصفوفة PHP زائدة عن الحاجة إلى تعيينات خاصية كائن إلى الحقل (ازدواج الجهود) ، لا توجد مولدات رمز (تتطلب رمزًا التجديد في حالة تغير بنية قاعدة البيانات) ، لا توجد ملفات XML/YAML غبية لتكوين النماذج الخاصة بك ، لا توجد أوامر لا لزوم لها فقط لاسترداد سجل واحد. مع F3 ، لا تتطلب تغيير حجم حقل varchar
في MySQL تغييرًا في رمز التطبيق الخاص بك. تمشيا مع MVC و "فصل المخاوف" ، فإن مسؤول قاعدة البيانات لديه قدر كبير من التحكم في البيانات (والهياكل) كمصمم قالب على قوالب HTML/XML.
إذا كنت تفضل العمل مع قواعد بيانات NOSQL ، فإن أوجه التشابه في بناء جملة الاستعلام سطحية. في حالة MongoDB Data Mapper ، سيكون الرمز المكافئ هو:-
$ db = new DB Mongo ( ' mongodb://localhost:27017 ' , ' testdb ' );
$ user = new DB Mongo Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID ' => ' tarzan ' ]);
مع الرقصة ، يشبه بناء الجملة محرك قالب F3:-
$ db = new DB Jig ( ' db/data/ ' , DB Jig:: FORMAT_JSON );
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? ' , ' tarzan ' ]);
يقوم الإطار تلقائيًا بتعيين visits
الحقل في جدولنا إلى خاصية Mapper Data أثناء إنشاء مثيل للكائن ، أي $user=new DBSQLMapper($db,'users');
. بمجرد إنشاء الكائن ، $user->password
و $user->userID
بتخطيط password
وحقول userID
في الجدول الخاص بنا ، على التوالي.
لا يمكنك إضافة أو حذف حقل تم تعيينه ، أو تغيير بنية الجدول باستخدام ORM. يجب عليك القيام بذلك في MySQL ، أو أي محرك قاعدة بيانات تستخدمه. بعد إجراء التغييرات في محرك قاعدة البيانات الخاصة بك ، ستقوم خالية من الدهون تلقائيًا بمزامنة بنية الجدول الجديدة مع كائن Mapper البيانات عند تشغيل التطبيق الخاص بك.
يستمد F3 بنية Mapper Data مباشرة من مخطط قاعدة البيانات. لا تخمين. إنه يدرك الاختلافات بين محركات قاعدة بيانات MySQL و SQLite و MSSQL و Sybase و PostgreSQL.
يجب ألا تستخدم معرفات SQL كلمات محفوظة ، ويجب أن تقتصر على الأحرف الأبجدية الرقمية AZ
و 0-9
ورمز السطحي ( _
). أسماء الأعمدة التي تحتوي على مسافات (أو أحرف خاصة) وتحيط بها عروض الأسعار في تعريف البيانات غير متوافقة مع ORM. لا يمكن تمثيلها بشكل صحيح كخصائص كائن PHP.
دعنا نقول أننا نريد زيادة عدد زيارات المستخدم وتحديث السجل المقابل في جدول المستخدمين لدينا ، يمكننا إضافة الكود التالي:-
$ user -> visits ++;
$ user -> save ();
إذا أردنا إدراج سجل ، فإننا نتبع هذه العملية:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
// or $ user = new DB Mongo Mapper ($ db , 'users' );
// or $ user = new DB Jig Mapper ($ db , 'users' );
$ user -> userID = ' jane ' ;
$ user -> password = password_hash ( ' secret ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> visits = 0 ;
$ user -> save ();
ما زلنا نستخدم نفس طريقة save()
. ولكن كيف يعرف F3 متى يجب إدراج السجل أو تحديثه؟ في الوقت الذي يتم فيه تحريك كائن خريطة البيانات تلقائيًا من خلال استرجاع السجل ، يتتبع الإطار المفاتيح الأساسية للسجل (أو _id
، في حالة Mongodb و Jig) - لذلك يعرف أي سجل يجب تحديثه أو حذفه - حتى عندما يتم تغيير قيم المفاتيح الأساسية. لن يتم استرداد قيم البيانات التي تُستعير برمجياً - والتي لم يتم استرداد قيمها من قاعدة البيانات ، ولكنها ملء بالتطبيق - أي ذاكرة للقيم السابقة في مفاتيحها الأساسية. وينطبق الشيء نفسه على MongoDB و Jig ، ولكن باستخدام كائن _id
كمرجع. لذلك ، عندما قمنا بتثبيت كائن $user
أعلاه وملبأت خصائصه بالقيم من برنامجنا - دون استرداد سجل من جدول المستخدم ، يعرف F3 أنه ينبغي إدراج هذا السجل.
لن يكون كائن Mapper فارغًا بعد save()
. إذا كنت ترغب في إضافة سجل جديد إلى قاعدة البيانات الخاصة بك ، فيجب عليك أولاً تجفيف الخريطة:-
$ user -> reset ();
$ user -> userID = ' cheetah ' ;
$ user -> password = password_hash ( ' unknown ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> save ();
استدعاء save()
مرة ثانية دون استدعاء reset()
سيقوم ببساطة بتحديث السجل الذي تم توضيحه حاليًا بواسطة MAPPER.
على الرغم من أن مشكلة وجود مفاتيح أساسية في جميع الجداول في قاعدة البيانات الخاصة بك أمر جدال ، فإن F3 لا يمنعك من إنشاء كائن Mapper بيانات يتواصل مع جدول لا يحتوي على مفاتيح أساسية. العيب الوحيد هو: لا يمكنك حذف أو تحديث سجل معين لأنه لا توجد طريقة على الإطلاق لـ F3 لتحديد السجل الذي تشير إليه بالإضافة إلى حقيقة أن المراجع الموضعية غير موثوقة. معرفات الصف ليست محمولة عبر محركات SQL المختلفة وقد لا يتم إرجاعها بواسطة برنامج تشغيل قاعدة بيانات PHP.
لإزالة سجل تم تعيينه من جدولنا ، استدعاء طريقة erase()
على خريطة بيانات تلقائية. على سبيل المثال:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? AND password=? ' , ' cheetah ' , ' ch1mp ' ]);
$ user -> erase ();
سيكون بناء جملة استعلام Jig متشابهًا قليلاً:-
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? AND @password=? ' , ' cheetah ' , ' chimp ' ]);
$ user -> erase ();
ومكافئ MongoDB سيكون:-
$ user = new DB Mongo Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID ' => ' cheetah ' , ' password ' => ' chimp ' ]);
$ user -> erase ();
لمعرفة ما إذا كان Mapper الخاص بنا رطبًا أم لا:-
if ( $ user -> dry ())
echo ' No record matching criteria ' ;
لقد غطنا معالجات Crud. هناك بعض الطرق الإضافية التي قد تجدها مفيدة:-
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> copyFrom ( ' POST ' );
$ f3 -> get ( ' user ' )-> save ();
لاحظ أنه يمكننا أيضًا استخدام المتغيرات الخالية من الدهون كحاويات لكائنات Mapper. تقوم طريقة copyFrom()
بترطيب كائن Mapper بعناصر من متغير صفيف الإطار ، يجب أن يكون لمفاتيح الصفيف أسماء متطابقة لخصائص كائن Mapper ، والتي بدورها تتوافق مع أسماء حقل السجل. لذلك ، عند إرسال نموذج ويب (على افتراض أن سمة اسم HTML يتم تعيينها على userID
) ، يتم نقل محتويات حقل الإدخال هذا إلى $_POST['userID']
، وتكرارها بواسطة F3 في متغير POST.userID
الخاص به ، ويتم حفظها إلى الحقل المعين $user->userID
في قاعدة البيانات. تصبح العملية بسيطة للغاية إذا كان لديهم جميع عناصر مشابهة. الاتساق في مفاتيح الصفيف ، IE الأسماء الرمزية قالب ، أسماء متغيرات الإطار وأسماء الحقول هي المفتاح :)
من ناحية أخرى ، إذا أردنا استرداد سجل ونسخ قيم الحقل إلى متغير إطار للاستخدام لاحقًا ، مثل عرض القالب:-
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> load ([ ' userID=? ' , ' jane ' ]);
$ f3 -> get ( ' user ' )-> copyTo ( ' POST ' );
يمكننا بعد ذلك تعيين {{post.userid}} إلى سمة قيمة حقل الإدخال نفسه. لتلخيص ، سيبدو حقل إدخال HTML هكذا:-
< input type =" text " name =" userID " value =" {{ @POST.userID }} " />
أساليب Mapper save()
، update()
، copyFrom()
والمتغيرات المعلمة من load()
و erase()
آمنة من حقن SQL.
بشكل افتراضي ، تسترجع طريقة load()
فقط السجل الأول الذي يطابق المعايير المحددة. إذا كان لديك أكثر من حالة تلبي نفس حالة السجل الأول المحملة ، فيمكنك استخدام طريقة skip()
للتنقل:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ( ' visits>3 ' );
// Rewritten as a parameterized query
$ user -> load ([ ' visits>? ' , 3 ]);
// For MongoDB users : -
// $ user = new DB Mongo Mapper ($ db , 'users' );
// $ user - > load ([ 'visits' = > [ '$gt' = > 3 ]]);
// If you prefer Jig : -
// $ user = new DB Jig Mapper ($ db , 'users' );
// $ user - > load ( '@visits>?' , 3 );
// Display the userID of the first record that matches the criteria
echo $ user -> userID ;
// Go to the next record that matches the same criteria
$ user -> skip (); // Same as $ user - > skip ( 1 );
// Back to the first record
$ user -> skip (- 1 );
// Move three records forward
$ user -> skip ( 3 );
يمكنك استخدام $user->next()
كبديل عن $user->skip()
، و $user->prev()
إذا كنت تعتقد أنه يعطي المزيد من المعنى $user->skip(-1)
.
استخدم طريقة dry()
للتحقق مما إذا كنت قد قمت بمناورة ما وراء حدود مجموعة النتائج. ستعود dry()
بشكل صحيح إذا حاولت skip(-1)
في السجل الأول. ستعود أيضًا بشكل صحيح إذا skip(1)
في السجل الأخير الذي يلبي معايير الاسترجاع.
تقبل طريقة load()
وسيطة ثانية: مجموعة من الخيارات التي تحتوي على أزواج القيمة الرئيسية مثل:-
$ user -> load (
[ ' visits>? ' , 3 ],
[
' order ' => ' userID DESC '
'offset'=> 5 ,
' limit ' => 3
]
);
إذا كنت تستخدم MySQL ، فإن الاستعلام يترجم إلى:-
SELECT * FROM users
WHERE visits > 3
ORDER BY userID DESC
LIMIT 3 OFFSET 5 ;
هذه طريقة واحدة لتقديم البيانات في قطع صغيرة. فيما يلي طريقة أخرى لترابط النتائج:-
$ page = $ user -> paginate ( 2 , 5 ,[ ' visits>? ' , 3 ]);
في السيناريو أعلاه ، سوف يسترجع F3 السجلات التي تتطابق مع المعايير 'visits>3'
. بعد ذلك ، سوف يحد من النتائج إلى 5 سجلات (لكل صفحة) بدءًا من Page Offset 2 (0 على أساس). سيعود الإطار مجموعة تتكون من العناصر التالية:-
[subset] array of mapper objects that match the criteria
[count] number of subsets available
[pos] actual subset position
سيتم إرجاع موضع المجموعة الفرعية الفعلية التي تم إرجاعها إذا كانت الوسيطة الأولى paginate()
هي رقم سالب أو يتجاوز عدد المجموعات الفرعية الموجودة.
هناك حالات عندما تحتاج إلى استرداد قيمة محسوبة للحقل ، أو قيمة مرجعية من جدول آخر. أدخل الحقول الافتراضية. يتيح لك النمور المصغر SQL العمل على البيانات المستمدة من الحقول الموجودة.
لنفترض أن لدينا الجدول التالي محدد على النحو التالي:-
CREATE TABLE products
productID VARCHAR ( 30 ),
description VARCHAR ( 255 ),
supplierID VARCHAR ( 30 ),
unitprice DECIMAL ( 10 , 2 ),
quantity INT ,
PRIMARY KEY (productID)
);
لا يوجد حقل totalprice
، حتى نتمكن من إخبار الإطار بطلب من محرك قاعدة البيانات المنتج الحسابي للحقول:-
$ item = new DB SQL Mapper ( $ db , ' products ' );
$ item -> totalprice = ' unitprice*quantity ' ;
$ item -> load ([ ' productID=:pid ' , ' :pid ' => ' apple ' ]);
echo $ item -> totalprice ;
يحدد مقتطف الرمز أعلاه حقلًا افتراضيًا يسمى totalprice
والذي يتم حسابه عن طريق ضرب unitprice
حسب quantity
. يحفظ Mapper SQL هذه القاعدة/الصيغة ، لذلك عندما يحين الوقت لاسترداد السجل من قاعدة البيانات ، يمكننا استخدام الحقل الظاهري مثل حقل تم تعيينه العادي.
يمكنك الحصول على حقول افتراضية أكثر تعقيدًا:-
$ item -> mostNumber = ' MAX(quantity) ' ;
$ item -> load ();
echo $ item -> mostNumber ;
هذه المرة يسترجع الإطار المنتج بأعلى كمية (لاحظ أن طريقة load()
لا تحدد أي معايير ، لذلك سيتم معالجة جميع السجلات في الجدول). بالطبع ، سيظل عدد الحقل الافتراضي mostNumber
يمنحك الرقم الصحيح إذا كنت ترغب في تقييد التعبير على مجموعة محددة من السجلات التي تتطابق مع معايير محددة.
يمكنك أيضًا استخلاص قيمة من جدول آخر:-
$ item -> supplierName =
' SELECT name FROM suppliers ' .
' WHERE products.supplierID=suppliers.supplierID ' ;
$ item -> load ();
echo $ item -> supplierName ;
في كل مرة تقوم فيها بتحميل سجل من جدول المنتجات ، المرجع المتقاطع ORM supplerID
في جدول products
مع supplierID
في جدول suppliers
.
لتدمير حقل افتراضي ، استخدم unset($item->totalPrice);
. يعود تعبير isset($item->totalPrice)
بشكل صحيح إذا تم تعريف الحقل الظاهري totalPrice
، أو خطأ إذا كان ذلك.
تذكر أنه يجب تعريف الحقل الافتراضي قبل استرجاع البيانات. لا يقوم ORM بإجراء الحساب الفعلي ، ولا اشتقاق النتائج من جدول آخر. إنه محرك قاعدة البيانات الذي يقوم بكل العمل الشاق.
إذا لم تكن هناك حاجة للتنقل سجلًا على حدة ، فيمكنك استرداد مجموعة كاملة من السجلات في لقطة واحدة:-
$ frequentUsers = $ user -> find ([ ' visits>? ' , 3 ],[ ' order ' => ' userID ' ]);
بناء جملة استعلام Mapper للاستعلام يشبه طفيف:-
$ frequentUsers = $ user -> find ([ ' @visits>? ' , 3 ],[ ' order ' => ' userID ' ]);
الرمز المكافئ باستخدام MongoDB Mapper:-
$ frequentUsers = $ user -> find ([ ' visits ' =>[ ' $gt ' => 3 ]],[ ' userID ' => 1 ]);
تبحث طريقة find()
في جدول users
عن السجلات التي تتطابق مع المعايير ، وفرز النتيجة بواسطة userID
وإرجاع النتيجة كمجموعة من كائنات mapper. find('visits>3')
يختلف عن load('visits>3')
. يشير الأخير إلى كائن $user
. find()
ليس له أي تأثير على skip()
.
هام: إعلان حالة فارغة أو خالية أو سلسلة بطول صفري كوسيطة أول لـ find()
أو load()
سيسترجع جميع السجلات. تأكد من أنك تعرف ما تفعله - قد تتجاوز PHP Memory_limit على الجداول أو المجموعات الكبيرة.
تحتوي طريقة find()
على بناء الجملة التالي:-
find (
$ criteria ,
[
' group ' => ' foo ' ,
' order ' => ' foo,bar ' ,
' limit ' => 5 ,
' offset ' => 0
]
);
البحث () إرجاع مجموعة من الكائنات. كل كائن هو خريطة إلى سجل يطابق المعايير المحددة .:-
$ place = new DB SQL Mapper ( $ db , ' places ' );
$ list = $ place -> find ( ' state="New York" ' );
foreach ( $ list as $ obj )
echo $ obj -> city . ' , ' . $ obj -> country ;
إذا كنت بحاجة إلى تحويل كائن Mapper إلى مجموعة نقاطية ، فاستخدم طريقة cast()
:-
$ array = $ place -> cast ();
echo $ array [ ' city ' ]. ' , ' . $ array [ ' country ' ];
لاسترداد عدد السجلات في جدول يتطابق مع حالة معينة ، استخدم طريقة count()
.
if (! $ user -> count ([ ' visits>? ' , 10 ]))
echo ' We need a better ad campaign! ' ;
هناك أيضًا طريقة select()
تشبه find()
ولكنها توفر المزيد من التحكم الدقيق في الحقول التي يتم إرجاعها. إنه يحتوي على بناء جملة يشبه SQL:-
select (
' foo, bar, MIN(baz) AS lowest ' ,
' foo > ? ' ,
[
' group ' => ' foo, bar ' ,
' order ' => ' baz ASC ' ,
' limit ' => 5 ,
' offset ' => 3
]
);
يشبه إلى حد كبير طريقة find()
، select()
لا يغير محتويات كائن Mapper. إنه بمثابة طريقة راحة فقط للاستعلام عن جدول معين. قيمة الإرجاع لكلا الطريقتين هي مجموعة من كائنات Mapper. باستخدام dry()
لتحديد ما إذا كان قد تم العثور على سجل من خلال هذه الطرق غير مناسب. إذا لم تتطابق أي سجلات مع معايير find()
أو select()
، فإن قيمة الإرجاع عبارة عن صفيف فارغ.
إذا كنت ترغب في معرفة أي عبارات SQL التي تم إصدارها مباشرة من خلال تطبيقك (أو بشكل غير مباشر من خلال كائنات Mapper) التي تسبب اختناقات الأداء ، يمكنك القيام بذلك مع بسيطة:---
echo $ db -> log ();
يتتبع F3 جميع الأوامر الصادرة إلى برنامج تشغيل قاعدة بيانات SQL الأساسي ، بالإضافة إلى الوقت الذي يستغرقه كل عبارة لإكمال - فقط المعلومات الصحيحة التي تحتاجها لتعديل أداء التطبيق.
في معظم الحالات ، يمكنك العيش من خلال وسائل الراحة التي قدمتها أساليب Mapper التي ناقشناها حتى الآن. إذا كنت بحاجة إلى إطار عمل للقيام ببعض الأعمال الشاقة ، فيمكنك تمديد خريطة SQL من خلال إعلان الفصول الدراسية الخاصة بك بطرق مخصصة- ولكن لا يمكنك تجنب الحصول على يديك الدهنية على بعض SQL المتشددين:--
class Vendor extends DB SQL Mapper {
// Instantiate mapper
function __construct ( DB SQL $ db ) {
// This is where the mapper and DB structure synchronization occurs
parent :: __construct ( $ db , ' vendors ' );
}
// Specialized query
function listByCity () {
return $ this -> select (
' vendorID,name,city ' ,[ ' order ' => ' city DESC ' ]);
/ *
We could have done the the same thing with plain vanilla SQL : -
return $ this - > db - > exec (
'SELECT vendorID,name,city FROM vendors ' .
'ORDER BY city DESC;'
);
* /
}
}
$ vendor = new Vendor ;
$ vendor -> listByCity ();
يعد توسيع نطاق البيانات بهذه الطريقة وسيلة سهلة لبناء النماذج المتعلقة بتطبيق DB الخاص بك.
إذا كنت مفيدًا مع SQL ، فمن المحتمل أن تقول: يمكن التعامل مع كل شيء في ORM مع استعلامات SQL في المدرسة القديمة. بالفعل. يمكننا الاستغناء عن مستمعي الأحداث الإضافيين باستخدام مشغلات قاعدة البيانات والإجراءات المخزنة. يمكننا إنجاز الاستعلامات العلائقية مع الجداول المنقولة. ORM هو مجرد النفقات العامة غير الضرورية. لكن النقطة هي - يمنحك مُرسم البيانات الوظائف المضافة لاستخدام الكائنات لتمثيل كيانات قاعدة البيانات. كمطور ، يمكنك كتابة التعليمات البرمجية بشكل أسرع وأن تكون أكثر إنتاجية. سيكون البرنامج الناتج أكثر نظافة ، إن لم يكن أقصر. ولكن سيتعين عليك وزن الفوائد مقابل التسوية في السرعة - خاصة عند التعامل مع مخازن البيانات الكبيرة والمعقدة. تذكر أن جميع Orms - بغض النظر عن مدى رقيقة - ستكون دائمًا مجرد طبقة تجريدية أخرى. لا يزال يتعين عليهم نقل العمل إلى محركات SQL الأساسية.
حسب التصميم ، لا يوفر ORMs F3 طرقًا لتوصيل الكائنات مباشرة ببعضها البعض ، أي SQL ينضم - لأن هذا يفتح علبة من الديدان. إنه يجعل تطبيقك أكثر تعقيدًا مما ينبغي ، وهناك ميل للأشياء من خلال تقنيات حريصة أو كسول لتكون مميتة وحتى خارج المزامنة بسبب الميراث الكائن والتعدد متعدد (عدم تطابق المعاوقة) مع كيانات قاعدة البيانات التي تم تعيينها عليها . هناك طرق غير مباشرة للقيام بذلك في SQL Mapper ، باستخدام الحقول الافتراضية - ولكن عليك القيام بذلك برمجيًا وعلى مسؤوليتك الخاصة.
إذا كنت مغريًا لتطبيق مفاهيم OOP "النقية" في تطبيقك لتمثيل جميع بياناتك (لأن "كل شيء كائن") ، ضع في اعتبارك أن البيانات تعيش دائمًا لفترة أطول من التطبيق. قد يكون برنامجك قديمًا قبل أن تفقد البيانات قيمته. لا تضيف طبقة أخرى من التعقيد في برنامجك باستخدام الكائنات والفئات المتشابكة التي تنحرف كثيرًا عن المخطط والبنية المادية للبيانات.
قبل أن تنسج كائنات متعددة معًا في تطبيقك لمعالجة الجداول الأساسية في قاعدة البيانات الخاصة بك ، فكر في هذا: إن إنشاء طرق عرض لتمثيل العلاقات والمشغلات لتحديد سلوك الكائن في محرك قاعدة البيانات أكثر كفاءة. تم تصميم محركات قاعدة البيانات العلائقية للتعامل مع المشاهدات والجداول والمحفزات. فهي ليست متاجر بيانات غبية. ستظهر الجداول المرتبطة في عرض كجدول واحد ، ويمكن لخريطة الخريطة الخالية من الدهون رسم عرض تلقائيًا تمامًا بالإضافة إلى جدول عادي. إن النسخ المتماثل يربط ككائنات علائقية في PHP أبطأ مقارنة برمز آلة محرك قاعدة البيانات والجبر العلائقي ومنطق التحسين. علاوة على ذلك ، فإن الانضمام إلى الجداول مرارًا وتكرارًا في تطبيقنا هو علامة أكيدة على أن تصميم قاعدة البيانات يحتاج إلى تدقيقه ، واعتبر طرق العرض جزءًا لا يتجزأ من استرجاع البيانات. إذا كان الجدول يستمر مرجع بيانات من جدول آخر بشكل متكرر ، ففكر في تطبيع الهياكل الخاصة بك أو إنشاء طريقة عرض بدلاً من ذلك. ثم قم بإنشاء كائن Mapper إلى الخريطة التلقائية لهذا العرض. إنه أسرع ويتطلب جهد أقل.
النظر في عرض SQL هذا الذي تم إنشاؤه داخل محرك قاعدة البيانات الخاص بك:-
CREATE VIEW combined AS
SELECT
projects . project_id AS project,
users . name AS name
FROM projects
LEFT OUTER JOIN users ON
projects . project_id = users . project_id AND
projects . user_id = users . user_id ;
يصبح رمز التطبيق الخاص بك بسيطًا لأنه ليس من الضروري الحفاظ على كائنين من خابطة (أحدهما لجدول المشاريع والآخر للمستخدمين) فقط لاسترداد البيانات من جدولين مرتبطين:-
$ combined = new DB SQL Mapper ( $ db , ' combined ' );
$ combined -> load ([ ' project=? ' , 123 ]);
echo $ combined -> name ;
نصيحة: استخدم الأدوات التي تم تصميمها لها. يحتوي Free Free بالفعل على مساعد SQL سهل الاستخدام. استخدمه إذا كنت بحاجة إلى مطرقة أكبر :) حاول البحث عن توازن بين الراحة والأداء. SQL will always be your fallback if you're working on complex and legacy data structures.
Plug-ins are nothing more than autoloaded classes that use framework built-ins to extend F3's features and functionality. If you'd like to contribute, leave a note at the Fat-Free Discussion Area hosted by Google Groups or tell us about it in the FreeNode #fatfree
IRC channel. Someone else might be involved in a similar project. The framework community will appreciate it a lot if we unify our efforts.
There might be instances when you want to make your forms more secure against spam bots and malicious automated scripts. F3 provides a captcha()
method to generate images with random text that are designed to be recognizable only by humans.
$ img = new Image ();
$ img -> captcha ( ' fonts/CoolFont.ttf ' , 16 , 5 , ' SESSION.captcha_code ' );
$ img -> render ();
This example generates an random image based on your desired TrueType font. The fonts/
folder is a subfolder within application's UI
path. The second parameter indicates the font size, and the third argument defines the number of hexadecimal characters to generate.
The last argument represents an F3 variable name. This is where F3 will store the string equivalent of the CAPTCHA image. To make the string reload-safe, we specified a session variable:- SESSION.captcha_code
which maps to $_SESSION['captcha_code']
, which you can use later to verify whether the input element in the form submitted matches this string.
We've covered almost every feature available in the framework to run a stand-alone Web server. For most applications, these features will serve you quite well. But what do you do if your application needs data from another Web server on the network? F3 has the Web plugin to help you in this situation:-
$ web = new Web ;
$ request = $ web -> request ( ' http://www.google.com/ ' );
// another way to do it : -
$ request =Web:: instance ()-> request ( ' http://www.google.com/ ' );
This simple example sends an HTTP request to the page located at www.google.com and stores it in the $request
PHP variable. The request()
method returns an array containing the HTTP response such that $request['headers']
and $request['body']
represent the response headers and body, respectively. We could have saved the contents using the F3::set command, or echo'ed the output directly to our browser. Retrieving another HTML page on the net may not have any practical purpose. But it can be particularly useful in ReSTful applications, like querying a CouchDB server.
$ host = ' localhost:5984 ' ;
$ web -> request ( $ host . ' /_all_dbs ' ),
$ web -> request ( $ host . ' /testdb/ ' ,[ ' method ' => ' PUT ' ]);
You may have noticed that you can pass an array of additional options to the request()
method:-
$ web -> request (
' https://www.example.com:443? ' .
http_build_query (
[
' key1 ' => ' value1 ' ,
' key2 ' => ' value2 '
]
),
[
' headers ' =>[
' Accept: text/html,application/xhtml+xml,application/xml ' ,
' Accept-Language: en-us '
],
' follow_location ' => FALSE ,
' max_redirects ' => 30 ,
' ignore_errors ' => TRUE
]
);
If the framework variable CACHE
is enabled, and if the remote server instructs your application to cache the response to the HTTP request, F3 will comply with the request and retrieve the cached response each time the framework receives a similar request from your application, thus behaving like a browser.
Fat-Free will use whatever means are available on your Web server for the request()
method to run: PHP stream wrappers ( allow_url_fopen
), cURL module, or low-level sockets.
F3 has a utility for sending files to an HTTP client, ie fulfilling download requests. You can use it to hide the real path to your download files. This adds some layer of security because users won't be able to download files if they don't know the file names and their locations. Here's how it's done:-
$ f3 -> route ( ' GET /downloads/@filename ' ,
function ( $ f3 , $ args ) {
// send () method returns FALSE if file doesn ' t exist
if (!Web:: instance ()-> send ( ' /real/path/ ' . $ args [ ' filename ' ]))
// Generate an HTTP 404
$ f3 -> error ( 404 );
}
);
The request()
method can also be used in complex SOAP or XML-RPC applications, if you find the need for another Web server to process data on your computer's behalf - thus harnessing the power of distributing computing. W3Schools.com has an excellent tutorial on SOAP. On the other hand, TutorialsPoint.com gives a nice overview of XML-RPC.
Caching static Web pages - so the code in some route handlers can be skipped and templates don't have to be reprocessed - is one way of reducing your Web server's work load so it can focus on other tasks. You can activate the framework's cache engine by providing a third argument to the $f3->route()
method. Just specify the number of seconds before a cached Web page expires:-
$ f3 -> route ( ' GET /my_page ' , ' App->method ' , 60 );
وإليك كيف يعمل. In this example, when F3 detects that the URL /my_page
is accessed for the first time, it executes the route handler represented by the second argument and saves all browser output to the framework's built-in cache (server-side). A similar instruction is automatically sent to the user's Web browser (client-side), so that instead of sending an identical request to the server within the 60-second period, the browser can just retrieve the page locally. The framework uses the cache for an entirely different purpose - serving framework-cached data to other users asking for the same Web page within the 60-second time frame. It skips execution of the route handler and serves the previously-saved page directly from disk. When someone tries to access the same URL after the 60-second timer has lapsed, F3 will refresh the cache with a new copy.
Web pages with static data are the most likely candidates for caching. Fat-Free will not cache a Web page at a specified URL if the third argument in the $f3->route()
method is zero or unspecified. F3 conforms to the HTTP specifications: only GET and HEAD requests can be cached.
Here's an important point to consider when designing your application. Don't cache Web pages unless you understand the possible unwanted side-effects of the cache at the client-side. Make sure that you activate caching on Web pages that have nothing to do with the user's session state.
For example, you designed your site in such a way that all your Web pages have the menu options: "Home"
, "About Us"
, and "Login"
, displayed when a user is not logged into your application. You also want the menu options to change to: "Home"
, "About Us"
, and "Logout"
, once the user has logged in. If you instructed Fat-Free to cache the contents of "About Us"
page (which includes the menu options), it does so and also sends the same instruction to the HTTP client. Regardless of the user's session state, ie logged in or logged out, the user's browser will take a snapshot of the page at the session state it was in. Future requests by the user for the "About Us"
page before the cache timeout expires will display the same menu options available at that time the page was initially saved. Now, a user may have already logged in, but the menu options are still the same as if no such event occurred. That's not the kind of behavior we want from our application.
Some pointers:-
GET
routes only. It will not cache submitted forms!Don't activate the cache on Web pages that at first glance look static. In our example, the "About Us" content may be static, but the menu isn't."About Us"
page, make sure it's available only when a user is not logged in.CACHE
global variable so it points to that drive. This will make your application run like a Formula 1 race car. Note: Don't set the timeout value to a very long period until you're ready to roll out your application, ie the release or production state. Changes you make to any of your PHP scripts may not have the expected effect on the displayed output if the page exists in the framework cache and the expiration period has not lapsed. If you do alter a program that generates a page affected by the cache timer and you want these changes to take effect immediately, you should clear the cache by erasing the files in the cache/ directory (or whatever path the CACHE
global variable points to) . F3 will automatically refresh the cache if necessary. At the client-side, there's little you can do but instruct the user to clear the browser's cache or wait for the cache period to expire.
PHP needs to be set up correctly for the F3 cache engine to work properly. Your operating system timezone should be synchronized with the date.timezone setting in the php.ini
file.
Similar to routes, Fat-Free also allows you to cache database queries. Speed gains can be quite significant, specially when used on complex SQL statements that involve look-up of static data or database content that rarely changes. Activating the database query cache so the framework doesn't have to re-execute the SQL statements every time is as simple as adding a 3rd argument to the F3::sql command - the cache timeout. على سبيل المثال:-
$ db -> exec ( ' SELECT * from sizes; ' , NULL , 86400 );
If we expect the result of this database query to always be Small
, Medium
, and Large
within a 24-hour period, we specify 86400
seconds as the 2nd argument so Fat-Free doesn't have to execute the query more than once a day . Instead, the framework will store the result in the cache, retrieve it from the cache every time a request comes in during the specified 24-hour time frame, and re-execute the query when the timer lapses.
The SQL data mapper also uses the cache engine to optimize synchronization of table structures with the objects that represent them. The default is 60
seconds. If you make any changes to a table's structure in your database engine, you'll have to wait for the cache timer to expire before seeing the effect in your application. You can change this behavior by specifying a third argument to the data mapper constructor. Set it to a high value if you don't expect to make any further changes to your table structure.
$ user = new DB SQL Mapper ( $ db , ' users ' , 86400 );
By default, Fat-Free's cache engine is disabled. You can enable it and allow it to auto-detect APC, WinCache or XCache. If it cannot find an appropriate backend, F3 will use the filesystem, ie the tmp/cache/
folder:-
$ f3 -> set ( ' CACHE ' , TRUE );
Disabling the cache is as simple as:-
$ f3 -> set ( ' CACHE ' , FALSE );
If you wish to override the auto-detection feature, you can do so - as in the case of a Memcached back-end which F3 also supports:-
$ f3 -> set ( ' CACHE ' , ' memcache=localhost:11211 ' );
You can also use the cache engine to store your own variables. These variables will persist between HTTP requests and remain in cache until the engine receives instructions to delete them. To save a value in the cache:-
$ f3 -> set ( ' var ' , ' I want this value saved ' , 90 );
$f3->set()
method's third argument instructs the framework to save the variable in the cache for a 90-second duration. If your application issues a $f3->get('var')
within this period, F3 will automatically retrieve the value from cache. In like manner, $f3->clear('var')
will purge the value from both cache and RAM. If you want to determine if a variable exists in cache, `$f3->exists('var')); returns one of two possible values: FALSE if the framework variable passed does not exist in cache, or an integer representing the time the variable was saved (Un*x time in seconds, with microsecond precision).
Fat-Free also has a Javascript and CSS compressor available in the Web plug-in. It can combine all your CSS files into one stylesheet (or Javascript files into a single script) so the number of components on a Web page are decreased. Reducing the number of HTTP requests to your Web server results in faster page loading. First you need to prepare your HTML template so it can take advantage of this feature. Something like:-
< link rel =" stylesheet " type =" text/css "
href =" /minify/css?files=typo.css,grid.css " />
Do the same with your Javascript files:-
< script type =" text/javascript " src =" /minify/js?&files=underscore.js " >
</ script >
Of course we need to set up a route so your application can handle the necessary call to the Fat-Free CSS/Javascript compressor:-
$ f3 -> route ( ' GET /minify/@type ' ,
function ( $ f3 , $ args ) {
$ f3 -> set ( ' UI ' , $ args [ ' type ' ]. ' / ' );
echo Web:: instance ()-> minify ( $ _GET [ ' files ' ]);
},
3600
);
And that's all there is to it! minify()
reads each file ( typo.css
and grid.css
in our CSS example, underscore.js
in our Javascript example), strips off all unnecessary whitespaces and comments, combines all of the related items as a single Web page component, and attaches a far-future expiry date so the user's Web browser can cache the data. It's important that the PARAMS.type
variable base points to the correct path. Otherwise, the URL rewriting mechanism inside the compressor won't find the CSS/Javascript files.
In our examples, the framework sends a far-future expiry date to the client's Web browser so any request for the same CSS or Javascript block will come from the user's hard drive. On the server side, F3 will check each request and see if the CSS or Javascript blocks have already been cached. The route we specified has a cache refresh period of 3600
seconds. Additionally, if the Web browser sends an If-Modified-Since
request header and the framework sees the cache hasn't changed, F3 just sends an HTTP 304 Not Modified
response so no content is actually delivered. Without the If-Modified-Since
header, Fat-Free renders the output from the cached file if available. Otherwise, the relevant code is executed.
Tip: If you're not modifying your Javascript/CSS files frequently (as it would be if you're using a Javascript library like jQuery, MooTools, Dojo, etc.), consider adding a cache timer to the route leading to your Javascript/CSS minify handler (3rd argument of F3::route()) so Fat-Free doesn't have compress and combine these files each time such a request is received.
Want to make your site run even faster? Fat-Free works best with either Alternative PHP Cache (APC), XCache, or WinCache. These PHP extensions boost performance of your application by optimizing your PHP scripts (including the framework code).
A fast application that processes all HTTP requests and responds to them at the shortest time possible is not always a good idea - specially if your bandwidth is limited or traffic on your Web site is particularly heavy. Serving pages ASAP also makes your application vulnerable to Denial-of-Service (DOS) attacks. F3 has a bandwidth throttling feature that allows you to control how fast your Web pages are served. You can specify how much time it should take to process a request:-
$ f3 -> route ( ' /throttledpage ' , ' MyApp->handler ' , 0 , 128 );
In this example, the framework will serve the Web page at a rate of 128KiBps.
Bandwidth throttling at the application level can be particularly useful for login pages. Slow responses to dictionary attacks is a good way of mitigating this kind of security risk.
Robust applications are the result of comprehensive testing. Verifying that each part of your program conforms to the specifications and lives up to the expectations of the end-user means finding bugs and fixing them as early as possible in the application development cycle.
If you know little or nothing about unit testing methodologies, you're probably embedding pieces of code directly in your existing program to help you with debugging. That of course means you have to remove them once the program is running. Leftover code fragments, poor design and faulty implementation can creep up as bugs when you roll out your application later.
F3 makes it easy for you to debug programs - without getting in the way of your regular thought processes. The framework does not require you to build complex OOP classes, heavy test structures, and obtrusive procedures.
A unit (or test fixture) can be a function/method or a class. Let's have a simple example:-
function hello () {
return ' Hello, World ' ;
}
Save it in a file called hello.php
. Now how do we know it really runs as expected? Let's create our test procedure:-
$ f3 = require ( ' lib/base.php ' );
// Set up
$ test = new Test ;
include ( ' hello.php ' );
// This is where the tests begin
$ test -> expect (
is_callable ( ' hello ' ),
' hello() is a function '
);
// Another test
$ hello = hello ();
$ test -> expect (
! empty ( $ hello ),
' Something was returned '
);
// This test should succeed
$ test ->expect
is_string ( $ hello ),
' Return value is a string '
);
// This test is bound to fail
$ test -> expect (
strlen ( $ hello )== 13 ,
' String length is 13 '
);
// Display the results ; not MVC but let ' s keep it simple
foreach ( $ test -> results () as $ result ) {
echo $ result [ ' text ' ]. ' <br /> ' ;
if ( $ result [ ' status ' ])
echo ' Pass ' ;
else
echo ' Fail ( ' . $ result [ ' source ' ]. ' ) ' ;
echo ' <br /> ' ;
}
Save it in a file called test.php
. This way we can preserve the integrity of hello.php
.
Now here's the meat of our unit testing process.
F3's built-in Test
class keeps track of the result of each expect()
call. The output of $test->results()
is an array of arrays with the keys text
(mirroring argument 2 of expect()
), status
(boolean representing the result of a test), and source
(file name/line number of the specific test) to aid in debugging.
Fat-Free gives you the freedom to display test results in any way you want. You can have the output in plain text or even a nice-looking HTML template. So how do we run our unit test? If you saved test.php
in the document root folder, you can just open your browser and specify the address http://localhost/test.php
. That's all there is to it.
F3 gives you the ability to simulate HTTP requests from within your PHP program so you can test the behavior of a particular route. Here's a simple mock request:-
$ f3 -> mock ( ' GET /test?foo=bar ' );
To mock a POST request and submit a simulated HTML form:-
$ f3 -> mock ( ' POST /test ' ,[ ' foo ' => ' bar ' ]);
Once you get the hang of testing the smallest units of your application, you can then move on to the bigger components, modules, and subsystems - checking along the way if the parts are correctly communicating with each other. Testing manageable chunks of code leads to more reliable programs that work as you expect, and weaves the testing process into the fabric of your development cycle. The question to ask yourself is:- Have I tested all possible scenarios? More often than not, those situations that have not been taken into consideration are the likely causes of bugs. Unit testing helps a lot in minimizing these occurrences. Even a few tests on each fixture can greatly reduce headaches. On the other hand, writing applications without unit testing at all invites trouble.
string AGENT
Mozilla/5.0 (Linux; Android 4.2.2; Nexus 7) AppleWebKit/537.31
. bool AJAX
TRUE
if an XML HTTP request is detected, FALSE
otherwise. string AUTOLOAD
|
), comma ( ,
), or semi-colon ( ;
) as path separator. string BASE
index.php
main/front controller. string BODY
bool/string CACHE
'memcache=localhost'
(and the PHP memcache module is present), F3 auto-detects the presence of APC, WinCache and XCache and uses the first available PHP module if set to TRUE. If none of these PHP modules are available, a filesystem-based backend is used (default directory: tmp/cache
). The framework disables the cache engine if assigned a FALSE
value. bool CASELESS
FALSE
to make it case-sensitive. array COOKIE, GET, POST, REQUEST, SESSION, FILES, SERVER, ENV
integer DEBUG
string DNSBL
403 Forbidden
error if the user's IPv4 address is listed on the specified server(s). array DIACRITICS
string ENCODING
UTF-8
. array ERROR
ERROR.code
is the HTTP status code. ERROR.status
contains a brief description of the error. ERROR.text
provides more detail. For HTTP 500 errors, use ERROR.trace
to retrieve the stack trace. bool ESCAPE
string EXEMPT
string FALLBACK
bool HALT
array HEADERS
bool HIGHLIGHT
TRUE
(requires code.css
stylesheet). string HOST
$_SERVER['SERVER_NAME']
is not available, return value of gethostname()
is used. string IP
array JAR
string LANGUAGE
LOCALES
. If set to NULL
, language is auto-detected from the HTTP Accept-Language
request header. string LOCALES
string LOGS
mixed ONERROR
string PACKAGE
array PARAMS
route()
pattern. PARAMS.0
contains the captured URL relative to the Web root. string PATTERN
string PLUGINS
base.php
. int PORT
string PREFIX
bool QUIET
bool RAW
BODY
. Should be TRUE when processing large data coming from php://input
which will not fit in memory. Default value: FALSE
string REALM
string RESPONSE
QUIET
setting. string ROOT
array ROUTES
string SCHEME
http
or https
. string SERIALIZER
php
, unless PHP igbinary
extension is auto-detected. Assign json
if desired. string TEMP
tmp/
folder inside the Web root. Adjust accordingly to conform to your site's security policies. string TZ
date_default_timezone_set()
function. string UI
View
and Template
classes' render()
method. Default value is the Web root. Accepts a pipe ( |
), comma ( ,
), or semi-colon ( ;
) as separator for multiple paths. callback UNLOAD
string UPLOADS
string URI
string VERB
string VERSION
@token
@token
with value of equivalent F3 variable. {{ mixed expr }}
expr
may include template tokens, constants, operators (unary, arithmetic, ternary and relational), parentheses, data type converters, and functions. If not an attribute of a template directive, result is echoed. {{ string expr | raw }}
expr
. F3 auto-escapes strings by default. {{ string expr | esc }}
expr
. This is the default framework behavior. The | esc
suffix is only necessary if ESCAPE
global variable is set to FALSE
. {{ string expr, arg1, ..., argN | format }}
expr
and pass the comma-separated arguments, where arg1, ..., argn
is one of:- 'date'
, 'time'
, 'number, integer'
, 'number, currency'
, or 'number, percent'
. <include
[ if="{{ bool condition }}" ]
href="{{ string subtemplate }}"
/>
subtemplate
and insert at current position in template if optional condition is TRUE
. <exclude>text-block</exclude>
text-block
at runtime. Used for embedding comments in templates. <ignore>text-block</ignore>
text-block
as-is, without interpretation/modification by the template engine. <check if="{{ bool condition }}">
<true>true-block</true>
<false>false-block</false>
</check>
TRUE
, then true-block
is rendered. Otherwise, false-block
is used. <loop
from="{{ statement }}"
to="{{ bool expr }}"
[ step="{{ statement }}" ]>
text-block
</loop>
from
statement once. Check if the expression in the to
attribute is TRUE
, render text-block
and evaluate step
statement. Repeat iteration until to
expression is FALSE
. <repeat
group="{{ array @group|expr }}"
[ key="{{ scalar @key }}" ]
value="{{ mixed @value }}"
[ counter="{{ scalar @key }}" ]>
text-block
</repeat>
text-block
as many times as there are elements in the array variable @group
or the expression expr
. @key
and @value
function in the same manner as the key-value pair in the equivalent PHP foreach()
statement. Variable represented by key
in counter
attribute increments by 1
with every iteration. <switch expr="{{ scalar expr }}">
<case value="{{ scalar @value|expr }}" break="{{ bool TRUE|FALSE }}">
text-block
</case>
.
.
.
</switch>
{* text-block *}
<exclude>
.The most up-to-date documentation is located at http://fatfreeframework.com/. It contains examples of usage of the various framework components.
Technical support is available at the official discussion forum: https://groups.google.com/forum/#!forum/f3-framework
. If you need live support, you can talk to the development team and other members of the F3 community via Slack or IRC. We're on the FreeNode #fatfree
channel ( chat.freenode.net
). Visit http://webchat.freenode.net/
to join the conversation. You can also download the Firefox Chatzilla add-on or Pidgin if you don't have an IRC client so you can participate in the live chat. You can also find help at Stack Overflow
F3 uses Git for version control. To clone the latest code repository on GitHub:
git clone git://github.com/bcosca/fatfree-core.git
If all you want is a zipball of our test bench with all unit tests, grab it here .
To file a bug report, visit https://github.com/bcosca/fatfree-core/issues
.
Fat-Free Framework is free and released as open source software covered by the terms of the GNU Public License (GPL v3). You may not use the software, documentation, and samples except in compliance with the license. If the terms and conditions of this license are too restrictive for your use, alternative licensing is available for a very reasonable fee.
If you feel that this software is one great weapon to have in your programming arsenal, it saves you a lot of time and money, use it for commercial gain or in your business organization, please consider making a donation to the project. A significant amount of time, effort, and money has been spent on this project. Your donations help keep this project alive and the development team motivated. Donors and sponsors get priority support (24-hour response time on business days).
The Fat-Free Framework is community-driven software. It can't be what it is today without the help and support from the following people and organizations:
Special thanks to the selfless others who expressed their desire to remain anonymous, yet share their time, contribute code, send donations, promote the framework to a wider audience, as well as provide encouragement and regular financial assistance. Their generosity is F3's prime motivation.
By making a donation to this project you signify that you acknowledged, understood, accepted, and agreed to the terms and conditions contained in this notice. Your donation to the Fat-Free Framework project is voluntary and is not a fee for any services, goods, or advantages, and making a donation to the project does not entitle you to any services, goods, or advantages. We have the right to use the money you donate to the Fat-Free Framework project in any lawful way and for any lawful purpose we see fit and we are not obligated to disclose the way and purpose to any party unless required by applicable law. Although Fat-Free Framework is free software, to our best knowledge this project does not have any tax-exempt status. The Fat-Free Framework project is neither a registered non-profit corporation nor a registered charity in any country. Your donation may or may not be tax-deductible; please consult this with your tax advisor. We will not publish/disclose your name and e-mail address without your consent, unless required by applicable law. Your donation is non-refundable.
Copyright (c) 2009-2022 F3::Factory/Bong Cosca <[email protected]>
يا المتأنق! Help me out for a couple of !