لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 05/05/17 في كل الموقع
-
يوفر Laravel 5 ميزة جديدة تسمى استعلامات الاستمارة Form Requests تساعد في معالجة بيانات الاستمارة والتحقق من صحتها. ستتعلم في هذا الدرس كيفية إنشاء استمارة اتصال في Laravel 5 باستخدام الميزة المذكورة وإمكانيات Laravel في إرسال البريد الإلكتروني. سنعرض طوال الدرس لميزات وحيل تقنية تتعلق بالتطوير على Laravel. تتكون استمارة الاتصال من ثلاثة حقول هي اسم المستخدم، وعنوان بريده الإلكتروني والرسالة التي يود إرسالها. ملحوظة: يفترض الدرس أن Laravel مثبت وجاهز للعمل. نبدأ بإنشاء مشروع Laravel جديد (أسميته academy) ثم الدخول إلى المجلد: laravel new academy cd academyيمكننا إنشاء متحكِّم Controller خاص بمعالجة استمارة الاتصال وعرضها إلا أننا سندمج هذه الوظيفة - للتسهيل - في المتحكِّم الذي يتولى الأمور الإدارية المتعلقة بالتطبيق. سننشئ لهذا الغرض متحكما باسم AboutController ونستخدم إجراءيْ create وstore لعرض استمارة الاتصال والتعامل معها (يقدم create الاستمارة عبر GET فيما يقدمها store عبر POST). سيستخدم AboutController إجراءات create ،index وstore فقط فسنكتفي بإنشاء متحكِّم بسيط عن طريق أمر artisan make:controller على النحو التالي: $ php artisan make:controller --plain AboutController Controller created successfullyنضيف كُنْيتيْن Aliases ضمن ملف app/Http/routes.php لتمكين الوصول إلى الاستمارة عبر المسار contact/: Route::get('contact', ['as' => 'contact', 'uses' => 'AboutController@create']); Route::post('contact', ['as' => 'contact_store', 'uses' => 'AboutController@store']);ينشئ أمر artisan make:controller السابق متحكما خاويا، نتيجة استخدام خيار plain-- مع artisan. أي أنه يتوجب علينا إضافة دالتَيْ create وstore في متحكم AboutController. عدل على المتحكِّم ليبدو على النحو التالي: <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Http\Controllers\Controller; class AboutController extends Controller { public function create() { return view('about.contact'); } public function store() { } } ملحوظة: يوجد المتحكم ضمن المسار app/Http/Controllers الموجود ضمن مجلد المشروع. كل المسارات المذكورة في الدرس تُنسَب إلى مجلد المشروع. ضبطنا إجراء create ليقدم عرضا View باسم contact.blade.php يوجد ضمن المسار resources/views/about. العرض contact.blade.php غير موجود لحد الساعة. فلننشئه. إنشاء استمارة الاتصاليوفر Laravel ميزات عدة لتصْيِير Rendering استمارات HTML. سنستخدم نظام Blade للقَوْلَبة Templating، المضمن في Laravel، لإنشاء الاستمارة. أنشئ مجلدا باسم about في المسار resources/views/ ثم أنشئ داخله ملفا باسم contact.blade.php. وألصق المحتوى التالي: <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> {!! Html::style('css/form.css') !!} <title>Academy Contact</title> </head> <body> <div id="page-wrap"> <h1>Academy contact</h1> <ul> @foreach($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> <div id="contact-area"> {!! Form::open(array('route' => 'contact_store', 'class' => 'form')) !!} {!! Form::label('Your Name') !!} {!! Form::text('name', null, array('required', 'placeholder'=>'Your name')) !!} {!! Form::label('Your E-mail Address') !!} {!! Form::text('email', null,array('required', 'placeholder'=>'Your e-mail address')) !!} {!! Form::label('Message') !!} {!! Form::textarea('message', null, array('required', 'id'=>'Message', 'cols'=>'20', 'rows'=>'20','placeholder'=>'Your message')) !!} {!! Form::submit('Contact Us!', array('class'=>'submit-button')) !!} {!! Form::close() !!} </div> </div> </body> </html>سنعود لشرح هذه الشفرة بعد قليل. 1- تفعيل مكون HTMLفي الاستمارة أعلاه استخدمنا مُنشِئ الاستمارات Form builder الموجود في مكون HTML؛ هذا المكون غير مفعل افتراضيا في Laravel 5. لتفعيله نفذ الخطوات التالية. عدل على ملف composer.json الموجود في مجلد المشروع وأضف التعليمة التالية ضمن خانة require: "illuminate/html": "~5.0"تصبح خانة require على الهيئة التالية بعد إضافة السطر (انتبه للفاصلة , في نهاية السطر الذي يسبق التعليمة التي أضفناها): "type": "project", "require": { "php": ">=5.5.9", "laravel/framework": "5.1.*", "illuminate/html": "~5.0" },حدث اعتماديات Dependencies المشروع عبر الأمر: composer update بعد انتهاء التحديث عدل على ملف config/app.php وأضف السطر التالي ضمن مصفوفة Providers (انتبه للفواصل): 'Illuminate\Html\HtmlServiceProvider',في نفس الملف أضف السطرين التاليين لمصفوفة Aliases: 'Form' => 'Illuminate\Html\FormFacade', 'Html' => 'Illuminate\Html\HtmlFacade',2- شرح آلية تصيير الاستمارةنعود لشرح طريقة إنشاء الاستمارة الموجودة عبر نظام Blade. نبدأ بأول تعليمة: {!! Html::style('css/form.css') !!}نطلب من نظام القوالب تحميل ملف CSS لاستخدامه في الصفحة. سيحمَّل ملف CSS في المكان الذي استُدعِيت فيه دالة style التابعة لصنف Html الذي عرَّفناه في الخطوة السابقة ضمن مصفوفة Aliases، هو وصنف Form. انتبه لكتابة اسم الصنف بنفس طريقة تعريفه في المصفوفة (Html وليس HTML). ملف form.css يوجد ضمن مجلد فرعي (باسم css) من مجلد Public. توضع الملفات المتاحة للعموم (مثل CSS وJavaScript) داخل هذا المجلد. ننتقل للتعليمتين: {!! Form::open(array('route' => 'contact_store', 'class' => 'form')) !!} ... {!! Form::close() !!}تعمل الدالتان Form::open وForm::close() معا من أجل إنشاء وسوم Tags فتح وإغلاق الاستمارة على التوالي. تستقبل دالة Form::open مصفوفة تمثل معطيات إعداد مختلفة؛ مثل كنية route(الوِجهة) التي تشير إلى دالة store ضمن المتحكم AboutController، وclass التي تشير إلى صنف CSS المستخدَم لتنسيق الاستمارة. يُستخدَم إجراء POST افتراضيا إلا أنه يمكن إبداله بGET عبر تمريره في المعطى method على النحو التالي 'method' => 'post'. تضيف دالة Form::open حقلا مخفِيّا عبارة عن رمز _token للحماية من هجمات تزوير الطلب عبر الموقع Cross-site request forgery, CSRF. ثم يأتي الدور على التعليمات التالية: <ul> @foreach($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul>تستخدم هذه التعليمات لإظهار رسائل تحقق إذا كانت مُدخَلات المستخدم غير مناسبة لطبيعة الحقول (سنعود لها لاحقا، لا تنسها). تظهر في ما بعد مجموعة من الدوال من أجل إنشاء حقول الاستمارة: Form::label لإنشاء لصائق Labels الحقول، Form::text لإنشاء حقول نصية، Form::textarea لإنشاء حقول نصية متعددة الأسطر، وForm::submit لإنشاء زر الإرسال. لاحظ أن دالتيْ Form::text وForm::text تحويان معطى باسم خاصية name الخاصة بالحقل (email، name وmessage على التوالي). أضفنا أيضا لكل حقل تشكيلة من الخيارات مثل أسماء أصناف التنسيقات وخصائص HTML. يمكنك بعد حفظ الملف تنفيذ الأمر التالي (من مجلد المشروع) لتشغيل تشغيل خادوم الويب المضمن في Laravel وتجربة النتيجة: php artisan serveأدخل العنوان http://localhost:8000/contact في المتصفح لعرض صفحة الاستمارة. ننتقل الآن، بعد إنشاء الاستمارة، لإعداد آلية التعامل مع محتوى الاستمارة وتمكين إرسال المقترحات عبرها. إنشاء استعلام استمارة الاتصاليضيف الإصدار الخامس من Laravel ميزة جديدة تعرف باستعلامات الاستمارة Form Requests؛ تهدف إلى وضع التصريح Authorization والتحقق من البيانات المرسَلة خارج المتحكِّمات وتغليفها ضمن صنف منفصل. نستخدم artisan لإنشاء استعلام Form request على النحو التالي: $ php artisan make:request ContactFormRequestينشئ الأمر ملفا باسم ContactFormRequest.php مساره app/Http/Requests/ContactFormRequest.php. يبدو هيكل الصنف، بعد حذف التعليقات، كما يلي: <?php namespace App\Http\Requests; use App\Http\Requests\Request; class ContactFormRequest extends Request { public function authorize() { return false; } public function rules() { return [ // ]; } }تحدد دالة authorize ما إذا كان يُسمح للمستخدم الحالي بالتفاعل مع الاستمارة. نريد أن يكون أي مستخدم قادرا على التفاعل مع الاستمارة، لذا نعدل الدالة لتكون القيمة المُرجَعة true بدلا من false. public function authorize() { return true; }تعرِّف دالة rules قواعد التحقق المرتبطة بحقول الاستمارة. الحقول الثلاثة، email، name وmessage جميعها مطلوبة (required)؛ كما أن حقل البريد الإلكتروني يجب أن يحوي عنوانا بريديا صالحا. نعدل دالة rules لإدراج هذه القواعد. public function rules() { return [ 'name' => 'required', 'email' => 'required|email', 'message' => 'required', ]; }توجد مدقِّقات Validators أخرى غير required وemail في Laravel للاستخدام عند الحاجة. لاحظ استخدام أكثر من مدقق في نفس الحقل مع الفصل بينها ب| مثل ما فعلنا مع حقل البريد الإلكتروني. احفظ ملف ContactFormRequest.php ثم افتح المتحكِّم AboutController (الموجود في المسار app/Http/Controllers/AboutController.php) وعدل دالة store لتصبح على النحو التالي: … use App\Http\Requests\ContactFormRequest; class AboutController extends Controller { public function store(ContactFormRequest $request) { return \Redirect::route('contact') ->with('message', 'Thanks for contacting us!'); } }لا تنس إضافة ;use App\Http\Requests\ContactFormRequest إلى المتحكم ليمكنه استخدام قواعد المصادقة المعرَّفة في الصنف ContactFormRequest.php الذي سيتولى التحقق من موافقة مُدخَلات المستخدم للقواعد الموضوعة ويظهر رسالة خطأ في حال أخلَّ المستخدم بإحداها. على سبيل المثال، إذا أدخل المستخدم عنوانا بريديا غير صالح فستظهر رسالة الخطأ التالية. طبعا لن تظهر رسائل الخطأ من العدم. تتولى مصفوفة errors$ المستخدمة في ملف contact.blade.php إظهار هذه الرسائل. هل تذكر هذه الشفرة؟ <ul> @foreach($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> نعود إلى ContactFormRequest.php. قد ترغب في إظهار رسالة (شكر مثلا) للمستخدم عند نجاح إرسال الاستمارة. تمكن إضافة رسالة سريعة ضمن دالة store. يضاف المتغير المُمرَّر للدالة تلقائيا إلى متغيرات الجلسة Session في Laravel مما يمكّن من استخدامها عبر الدالة Session::get. يمكِن على سبيل المثال استخدام الشفرة التالية لإظهار محتوى المتغير message في أي عرض (View) أثناء الجلسة: @if(Session::has('message')) <div class="alert alert-info"> {{Session::get('message')}} </div> @endifبقيت خطوة واحدة لتكون الاستمارة جاهزة لإرسال بريد إلكتروني. نحتاج لإعداد مكوِّن البريد في Laravel وإدماج وظيفة تسليم البريد إلى دالة store. إعداد مكوِّن البريد في Laravelيستخدم Laravel حزمة SwiftMailer لتوفير إمكانية إرسال بريد إلكتروني بيسر. كل ما عليك فعله هو ضبط الإعدادات الموجودة في ملف config/mail.php. نذكر في ما يلي بعض الإعدادات الموجودة في الملف. driver: يدعم Laravel عدة تعريفات بريد مثل SMTP، دالة بريد PHP (mail)، خادوم بريد Sendmail وخدمتَيْ Mailgun وMandrill لتسليم البريد. يجب أن تضبط الإعدادات على التعريف المرغوب بالاختيار بين mailgun، sendmail، mail،smtp و mandrill. host: تعيين اسم المستضيف لخادوم البريد الإلكتروني (عند استخدام التعريف smtp).port: تعيين اسم منفَذ خادوم البريد الإلكتروني (عند استخدام التعريف smtp).from: إذا رغبت في أن تستخدم كل الرسائل المرسَلة نفس العنوان البريدي والاسم للمرسِل فبإمكانك ضبط إعدادات from وaddress المعرَّفة في هذه المصفوفة.encryption: يحدد بروتوكول التعميّة Encryption المستخدَم لإرسال البريد الإلكتروني.username: يعين اسم المستخدم في حال كان التعريف smtp.password: كلمة سر المستخدم في حال كان التعريف smtp.sendmail: مسار خادوم Sendmail إذا كانت قيمة driver هي sendmail.pretend: يطلب هذا الإعداد من Laravl تجاهل التعريف المضبوط وإرسال البريد إلى سجل التطبيق بدلا منه. يناسب التطبيقات التي مازالت قيد التطوير والتجربة.نأخذ مثالا لإعداد إرسال البريد في Laravel لاستخدام حساب بريد Google. غير الإعدادات التالية مثل ماهو مبيَّن. أعط القيمة smtp للتعريف driver. هذه هي القيمة الافتراضية.أبدل قيمة host إلى smtp.google.comاستخدم المنفذ port رقم 465.أبدل التعميّة encryption إلى ssl.استخدم حساب البريد الإلكتروني ضمن إعداد username.اكتب كلمة سر حساب البريد الإلكتروني في إعداد password. تذكر أنه يجب، ضمن بيئة عمل فعلية، حفظ هذه المعلومات ومعلومات أخرى حساسة ضمن ملف env. في مشروعك أو في متغير البيئة في الخادوم.احفظ التعديلات على ملف config/mail.php ثم عدل المتحكم AboutController ليبدو على النحو التالي: public function store(ContactFormRequest $request) { \Mail::send('emails.contact', array( 'name' => $request->get('name'), 'email' => $request->get('email'), 'user_message' => $request->get('message') ), function($message) { $message->from('wj@wjgilmore.com'); $message->to('wj@wjgilmore.com', 'Admin')->subject('Academy Feedback'); }); return \Redirect::route('contact')->with('message', 'Thanks for contacting us!'); }الدالة Mail::send هي المسؤولة عن ابتداء عملية تسليم البريد، وتستقبل ثلاثة معطيات. يحدد المعطى الأول اسم العرض (View) المستخدم لقالب جسم (محتوى) البريد الإلكتروني. المعطى الثاني هو مصفوفة بالبيانات المتاحة للاستخدام في جسم البريد الإلكتروني. البيانات المتاحة في حالتنا هي تلك القادمة من استمارة الاتصال عبر الكائن request$. يمنح المعطى الثالث إمكانية تحديد خيارات إضافية للبريد الإلكتروني مثل المرسِل، المستقبِل والموضوع. سنحتاج لإنشاء العرض الذي توجد به محتويات البريد. لذا سننشئ ملفا باسم contact.blade.php في المسار resources/views/emails. طبعا يمكنك تغيير اسم ومجلد العرض؛ إن فعلت فلا تنس التعديل على المتحكم AboutController بما يوافقك تغييراتك. You received a message from academy.hsoub.com: <p> Name: {{ $name }} </p> <p> {{ $email }} </p> <p> {{ $user_message }} </p>ملحوظة: يوجد سجل التطبيق في المسار storage/logs/laravel.log. عند إعطاء القيمة true لpretend ستحاكي إرسال بريد دون أن ترسله فعليا وسيظهر سطر يشبه التالي في السجل: [2015-07-12 11:34:51] local.INFO: Pretending to mail message to: wj@wjgilmore.comعُد، بعد حفظ التعديلات، إلى استمارة الاتصال؛ اكتب بيانات صحيحة ضمن حقول الاستمارة وأرسلها. يجب أن تصل الرسالة إلى البريد الموجود في دالة to (أي wj@wjgilmore.com في المثال). قد تواجه مشاكل مع إعدادات Gmail بسبب التقييدات على تطبيقات الطرف الثالث في Gmail. راجع إعدادات حساب Google في هذه الحالة. خاتمةاخترنا عرض جميع المخرجات المذكورة في هذا الدرس باللغة الإنجليزية للتركيز على الخاصية المشروحة. إن أردت توطين Localization المثال واستخدام اللغة العربية فيمكنك كتابة العبارات العربية مباشرة في ملفات القوالب لكن ستبقى رسائل الخطأ باللغة الإنجليزية ويجب عليك إدراج رسائل خطأ خاصة بالعربية. على العموم يُنصَح، لمن أراد توفير قابلية التوطين بسهولة، بعدم كتابة المُخرجات مباشرة في الشفرة Hard code بل إنشاء ملف بسلاسل المحارف Strings المستخدمة واستدعاء ملف اللغة المناسبة عن طريق دالة الترجمة trans. يُنشَأ مجلد لكل لغة مدعومة ضمن المسار resources/lang الذي يوجد فيه افتراضيا مجلد للغة الإنجليزية en به ملفات بالعبارات المستخدمة افتراضيا. ترجمة بتصرف لمقال Creating a Contact Form in Laravel 5 Using the Form Request Feature لصاحبه Jason Gilmore1 نقطة
-
تخيّل معي الوضع التالي. أنت عضو في فريق تطوير تطبيق باستخدام Laravel 4. يستخدم أعضاء الفريق git لإدارة إصدارات التطبيق وفي كل مرة يقوم عضو من أعضاء الفريق بإضافة خصائص أو إدخال تعديلات جديدة على المشروع يقوم بإيداع التغييرات في مُستودع التطبيق. إلى هنا يبدو الوضع عاديا (بل مثاليا) لكن ماذا لو قام أحد أعضاء الفريق بإدخال تعديل يتطلب إضافة جداول جديدة إلى قاعدة البيانات أو تعديل حقول وحذف أخرى، فما الحل هنا؟ هل يستطيع git مثلا أن يفي بالغرض؟ أم أنه سيتم تصدير قاعدة البيانات في كل مرة ويُطلب من كل عضو في الفريق استيرادها؟ ماذا عن البيانات التي تحتويها قاعدة البيانات؟ وهل يجب فعلا أن نتخلص من قاعدة البيانات القديمة واستبدالها بأخرى في كل مرة؟ إن كنت تستخدم إطار عمل لارافل فالحل يكمن في استخدام التهجير migrations والذي يُعتبر نظاما لإدارة الإصدارات الخاصة بقواعد البيانات، حيث أنه لن تعود هناك حاجة إلى إنشاء أي جداول أو إضافة حقول والتعديل عليها بشكل مُباشر/يدوي، وإنما يتم وصف تلك الجداول وحقولها بصيغة تجعل من التعامل مع قواعد البيانات أسهل. قد يبدو الأمر مُعقّدا بعض الشيء، لكنه في حقيقة الأمر بسيط، وبمُجرد أن تفهم آلية عمله وتشرع في استخدامه حتى تستغرب كيف ضيعت كل الوقت السابق في إدارة قواعد البيانات يدويا. خاصية migrations مُفيدة لك حتى ولو كنت تعمل على مشروعك بشكل فردي. بطبيعة الحال ستحتاج إلى إنشاء قاعدة بيانات للمشروع، ومن ثم التعديل على ملف app/config/database.php بما يتوافق مع ذلك. إنشاء ملفات migrationsلإنشاء ملف migration جديد نحتاج إلى استخدام artisan لتنفيذ الأمر migration:make على النحو التالي مع استبدال اسم عملية التهجير بما يتوافق مع ما تقوم به (بطبيعة الحال ستحتاج إلى تنفيذ هذا الأمر بسطر الأوامر لما تكون داخل مُجلد المشروع): php artisan migrate:make create_users_tableسيقوم laravel بإنشاء ملف جديد داخل مُجلد app/database/migrations يحمل الاسم الذي حددته في الأمر السابق ( create_users_table) مسبوقا بترقيم يُمثل تاريخ إنشائه حتى يتسنى لـ laravel معرفة الترتيب الذي يجب اتباعه لدى تنفيذ التهجيرات. يُفضل استخدام أسماء للتهجيرات تدل على ما تقوم به. ففي المثال السابق أردنا إنشاء عملية تهجير جديدة لإنشاء جدول مُستخدمين، وبالتالي كان الاسم create_users_table. ينتج عن تنفيذ الأمر السابق ملف يحتوي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { // } /** * Reverse the migrations. * * @return void */ public function down() { // } } كما هو ظاهر هنا فإن الصنف CreateUsersTable يحتوي على دالتين الأولى up والتي تُبين ما الذي يجب القيام به لدى تنفيذ التهجير، والثانية down والتي نُحدد فيها ما الذي يجب القيام به لدى إلغاء التهجير في حال ما إذا أردنا العودة بقاعدة البيانات إلى الحالة التي كانت عليها قبل تنفيذ التهجير. هذا الملف لا يُحدد أي جدول نعمل عليه أو نرغب في إنشاءه. يُمكن إضافة ذلك يدويا، كما أنه يُمكن القيام بذلك عبر تحديد اسم الجدول لدى تنفيذ أمر إنشاء عملية التهجير وذلك باستخدام --create التي تُحدد اسم الجدول الذي نرغب في إنشاءه أو --table التي تُحدد اسم الجدول الذي نرغب في التعديل عليه. فمثلا لو حذفنا عملية التهجير السابقة ورغبنا في إعادة إنشاء أخرى مع تحديد اسم الجدول فسيكون ذلك على النحو التالي: php artisan migrate:make create_users_table --create=usersوالذي سينتج عنه ملف مثل الملف السابق، لكن هذه المرة نجد أن دالتي up و down تحتويان أوامر أولية: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('user', function(Blueprint $table) { $table->increments('id'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('user'); } } لاحظ هنا أن users هي اسم الجدول المُراد إنشاؤه والذي يكون عادة جمع اسم الـ model الذي تتعامل معه (بمعنى إن كان user هو اسم الـ model فسيكون اسم الجدول الخاص به users) أما لو أردنا التعديل على نفس الجدول السابق وإضافة حقل جديد إليه فيكفي تنفيذ الأمر التالي: php artisan migrate:make add_votes_to_user_table --table=users تنفيذ عمليات التهجيرإلى حد الآن كل ما قمنا به هو إنشاء ملفات التهجير، حيث أنك لو تحققت من قاعدة البيانات لوجدتها فارغة. لتنفيذ عمليات التهجير نستعمل الأمر php artisan migrateوبعد ذلك ستلاحظ ظهور جدول جديد على قاعدة البيانات. أما لو رغبت في التراجع عن آخر عملية تهجير (أو بالأحرى عن آخر جملة تهجيرات تم تنفيذها مع بعض) فإننا نستعمل الأمر: php artisan migrate:rollbackوفي حال ما إذا رغبت في التراجع عن جميع عمليات التهجير والرجوع إلى الحالة الأولى لقاعدة البيانات فإن الأمر التالي كفيل بالقيام بذلك: php artisan migrate:resetويُمكن أيضا استخدام الأمر التالي للتخلص من جميع عمليات التهجير وإعادة تنفيذها من جديد بشكل مُباشر بعد ذلك: php artisan migrate:refreshأنواع الحقولرأينا في الفقرة السابقة بأن عمليات التهجير تسمح لنا بإنشاء معرف autoincrement إضافة إلى حقلي created_at و updated_at بفضل دالة timestamps. يسمح Laravel بإنشاء شتى أنواع الحقول التي قد تحتاجها في مشروعك إلى جانب إضافة خصائص للحقول وإعطائها قِيمًا أوليّة. المثال التالي يُبين بعض هذه الحقول والخصائص: $user->string('name', 64); $user->integer('age')->nullable(); $user->boolean('active')->default(1); $user->integer('role_id')->unsigned(); $user->text('bio');والذي يقوم بإنشاء: حقل name يكون نصيا يكون أقصر من أو يُساوي 64 محرفا.حقل age يكون رقميا، كما أنه يقبل القيمة NULLحقل active يكون منطقيا ويحمل قيمة أولية 1حقل role_id رقميا ويكون موجباحقل bio يكون نصيابإمكان الاطلاع على جميع أنواع الحقول المُمكنة من هنا حذف الحقولستحتاج إلى حذف الحقول في دالة down ويتم ذلك على النحو التالي: Schema::table('users', function($table) { $table->dropColumn('votes'); });بذر قواعد البيانات database seedingالمقصود ببذر قواعد البيانات هو إدخال البيانات الأولية التي نحتاجها لتجربة التطبيق. بالرغم من أن تطبيقك يسمح بإنشاء مُستخدمين جدد فإنك سترغب في استخدام مُستخدمين تجريبيين في كل مرة تُحدث تغييرات في التطبيق، وإنشاء عدد من المُستخدمين يدويا في كل مرة مضيعة للوقت. الحل يكمن في إعلام Laravel بالبيانات الأولية التي ترغب في بذر قاعدة البيانات بها بعد إنشائها ويتم ذلك عبر إنشاء ملفات بذر داخل مُجلد app/database/seeds يحتوي الأوامر التي يجب تنفيذها. مثال على ملف بذر يقوم بإضافة مُستخدم جديد: class UserTableSeeder extends Seeder { public function run() { DB::table('users')->delete(); User::create(array('email' => 'foo@bar.com')); } } لتنفيذ عملية البذر التي قمنا بإنشائها فإننا نستخدم الأمر التالي: php artisan db:seed --class=UserTableSeederوإن كان لديك أكثر من ملف بذر وترغب في تنفيذها كاملة بأمر واحد فإنه يكفي القيام بذلك عبر تحديد أسماء عمليات البذر المُراد تنفيذها في صنف/ملف DatabaseSeeder الذي ستجده داخل مُجلد app/database/seeds على النحو التالي: class DatabaseSeeder extends Seeder { public function run() { $this->call('UserTableSeeder'); $this->call('PostTableSeeder'); } }وبعد ستحتاج إلى تنفيذ الأمر php artisan db:seedالذي سيقوم بقراءة الملف واستدعاء عمليات البذر بشكل مُتوال بإمكانك أيضا تنفيذ عمليات البذر مُباشرة بعد تحديث عمليات التهجير على الشكل التالي: php artisan migrate:refresh --seedتوليد بيانات تجريبية باستخدام Fakerبالرغم من أن هذه الخُطوة ليست ضرورية، إلا أنه في الكثير من الحالات ستحتاج إلى بيانات تجريبية أقرب ما تكون إلى البيانات الحقيقية للتجريب عليها. فمثلا سترغب في استخدام أسماء مُستخدمين "حقيقيين" وعناوين بريد إلكتروني، وعناوين منازل، إضافة إلى أسماء المُدن وأرقام هواتف وما إلى ذلك. بطبيعة الحال فإنه بالإمكان الاكتفاء بملفات البذر وإدخال تلك البيانات بطريقة شبه يدوية، إلا أن هناك حلا آخر يُسهّل عليك ذلك إن استعنت بمكتبة Faker للحصول على هذه البيانات. بداية سنحتاج إلى "تنصيب" Faker وذلك على النحو التالي: قم بالتعديل على ملف composer.json وإضافة التالي: "require-dev":{ "fzaninotto/faker": "1.5.*@dev" },أو قم بإضافة "fzaninotto/faker": "1.5.*@dev" إن كان حقل require-dev مُتوفرا في الملف. بعدها قم بتنفيذ الأمر php artisan update ليقوم artisan بتحميل الملفات المطلوبة. في غالب الأحوال ستحتاج إلى إنشاء مُستخدم غير عشوائي إلى جانب البيانات التجريبية، وعليه يُفضل إنشاؤه أولا قبل توليد البيانات العشوائية. $user = User::create(array( 'username' => 'djug', 'first_name' => 'Youghourta', 'last_name' => 'Benali', 'email' => 'djug@someNewProject.com', 'password' => Hash::make('MySuperPassword') )); $faker = Faker\Factory::create(); for ($i = 0; $i < 25; $i++) { $user = User::create(array( 'username' => $faker->userName, 'first_name' => $faker->firstName, 'last_name' => $faker->lastName, 'email' => $faker->email, 'password' => Hash::make('Password') )); في هذا المثال قمنا بإنشاء 25 مُستخدم يحملون أسماء بشر (وليس مُجرد حروف عشوائية) إضافة إلى عناوين بريد إلكتروني. تسمح مكتبة Faker بتوليد شتى أنواع الحقول التي قد تحتاجها والتي يُمكن الحصول على نُسخ مُوطنة ومُترجمة منها، فمثلا يُمكن توليد أسماء عربية وعناوين فرنسية وما إلى ذلك. للمزيد حول مكتبة Faker قم بإلقاء نظرة على مُستودع المشروع على github وللمزيد حول جميع أنواع العمليات التي يُمكن القيام بها على الهجرات: Schema Builder1 نقطة
-
هده السكربت ضعه فوق </head> <script type='text/javascript'> //<![CDATA[ // Related Post Script var relatedTitles=[],relatedTitlesNum=0,relatedUrls=[],thumburl=[]; function related_results_labels_thumbs(f){for(var e=0;e<f.feed.entry.length;e++){var g=f.feed.entry[e];relatedTitles[relatedTitlesNum]=g.title.$t;try{thumburl[relatedTitlesNum]=g.media$thumbnail.url}catch(h){s=g.content.$t,a=s.indexOf("<img"),b=s.indexOf('src="',a),c=s.indexOf('"',b+5),d=s.substr(b+5,c-b-5),thumburl[relatedTitlesNum]=-1!=a&&-1!=b&&-1!=c&&""!=d?d:"undefined"!==typeof defaultnoimage?defaultnoimage:"http://3.bp.blogspot.com/-PpjfsStySz0/UF91FE7rxfI/AAAAAAAACl8/092MmUHSFQ0/s1600/no_image.jpg"}120<relatedTitles[relatedTitlesNum].length&& (relatedTitles[relatedTitlesNum]=relatedTitles[relatedTitlesNum].substring(0,120)+"...");for(var k=0;k<g.link.length;k++)"alternate"==g.link[k].rel&&(relatedUrls[relatedTitlesNum]=g.link[k].href,relatedTitlesNum++)}} function removeRelatedDuplicates_thumbs(){for(var f=[],e=[],g=[],h=0;h<relatedUrls.length;h++)contains_thumbs(f,relatedUrls[h])||(f.length+=1,f[f.length-1]=relatedUrls[h],e.length+=1,g.length+=1,e[e.length-1]=relatedTitles[h],g[g.length-1]=thumburl[h]);relatedTitles=e;relatedUrls=f;thumburl=g}function contains_thumbs(f,e){for(var g=0;g<f.length;g++)if(f[g]==e)return!0;return!1} function printRelatedLabels_thumbs(f){for(var e=0;e<relatedUrls.length;e++)relatedUrls[e]!=f&&relatedTitles[e]||(relatedUrls.splice(e,1),relatedTitles.splice(e,1),thumburl.splice(e,1),e--);f=Math.floor((relatedTitles.length-1)*Math.random());e=0;0<relatedTitles.length&&document.write("<h2>"+relatedpoststitle+"</h2>");for(document.write('<div style="clear: both;"/>');e<relatedTitles.length&&20>e&&e<maxresults;)document.write('<a style="text-decoration:none;'),document.write('"'),document.write(' href="'+ relatedUrls[f]+'"><img src="'+thumburl[f].replace("/s72-c/","/w207-h120-c/")+'"/><div class="relatedTitles">'+relatedTitles[f]+"</div></a>"),e++,f<relatedTitles.length-1?f++:f=0;document.write("</div>");relatedUrls.splice(0,relatedUrls.length);thumburl.splice(0,thumburl.length);relatedTitles.splice(0,relatedTitles.length)}; // Read More Script function removeHtmlTag(a,b){if(-1!=a.indexOf("<")){for(var c=a.split("<"),d=0;d<c.length;d++)-1!=c[d].indexOf(">")&&(c[d]=c[d].substring(c[d].indexOf(">")+1,c[d].length));a=c.join("")}for(b=b<a.length-1?b:a.length-2;" "!=a.charAt(b-1)&&-1!=a.indexOf(" ",b);)b++;a=a.substring(0,b-1);return a+"..."}function createSummary(a){a=document.getElementById(a);var b='<div class="postpe">'+removeHtmlTag(a.innerHTML,150)+"</div>";a.innerHTML=b}; //Recent Post Widget function repost1(c){for(var a=0;a<c.feed.entry.length;a++){for(var b=0;b<c.feed.entry[a].link.length;b++)if("alternate"==c.feed.entry[a].link[b].rel){var e=c.feed.entry[a].link[b].href;break}b="thr$total"in c.feed.entry[a]?c.feed.entry[a].thr$total.$t+" تعليقات ":"تعليقات معطلة";"تعليقات 1"==b&&(b="تعليقات 1");"تعليقات 0"==b&&(b="لا تعليقات");var d=c.feed.entry[a].published.$t,h=d.substring(0,4),k=d.substring(5,7),d=d.substring(8,10),l=c.feed.entry[a].title.$t,g=c.feed.entry[a].category[0].term, f=c.feed.entry[a].media$thumbnail.url;-1!=f.indexOf("img.youtube.com")&&(f=c.feed.entry[a].media$thumbnail.url.replace("default","0"));b='<div class="wrapper"><a href='+e+'><img src="'+f.replace("/s72-c/","/s209-h130-c/")+'"/></a><div class="repostt"><a href="/search/label/'+g+'?&max-results=8">'+g+"</a></div><h3><a href="+e+">"+l+'</h3></a><font class="reposth"> '+[,"يناير","فبراير","مارس","ابريل","مايو","يونيو","يوليو","أغسطس","سيبتمبر","أكتوبر", "نوفمبر","ديسيمبر"][parseInt(k,10)]+" "+ d+", "+h+" / <a href="+e+"#comments>"+b+"</a></font></div>";document.write(b)}}; //Recent Post Widget By Label function repostl1(c){for(var a=0;a<c.feed.entry.length;a++){for(var b=0;b<c.feed.entry[a].link.length;b++)if("alternate"==c.feed.entry[a].link[b].rel){var e=c.feed.entry[a].link[b].href;break}b="thr$total"in c.feed.entry[a]?c.feed.entry[a].thr$total.$t+" تعليقات ":"تعليقات معطلة";"1 تعليقات"==b&&(b="1 تعليق");"0 تعليقات"==b&&(b="لا تعليقات");var d=c.feed.entry[a].published.$t,h=d.substring(0,4),k=d.substring(5,7),d=d.substring(8,10),l=c.feed.entry[a].title.$t,g=c.feed.entry[a].category[0].term, f=c.feed.entry[a].media$thumbnail.url;-1!=f.indexOf("img.youtube.com")&&(f=c.feed.entry[a].media$thumbnail.url.replace("default","0"));b='<div class="wrapper"><div class="rp-lf-img"><a href='+e+'><img src="'+f.replace("/s72-c/","/s110-h85-c/")+'"/></a></div><div class="rp_lfc"><div class="repostt"><a href="/search/label/'+g+'?&max-results=8">'+g+"</a></div><h3><a href="+e+">"+l+'</h3></a><font class="reposth"> '+[,"يناير","فبراير","مارس","ابريل","مايو","يونيو","يوليو","أغسطس","سيبتمبر","أكتوبر", "نوفمبر","ديسيمبر"][parseInt(k,10)]+" "+d+", "+h+" / <a href="+e+"#comments>"+b+"</a></font></div></div>";document.write(b)}}; //Recent Post Widget For Full Widget function repostfw(b){for(var a=0;a<b.feed.entry.length;a++){for(var c=0;c<b.feed.entry[a].link.length;c++)if("alternate"==b.feed.entry[a].link[c].rel){var f=b.feed.entry[a].link[c].href;break}c="thr$total"in b.feed.entry[a]?b.feed.entry[a].thr$total.$t+" تعليقات":"تعليقات معطلة";"1 تعليقات"==c&&(c="1 تعليق");"0 تعليقات"==c&&(c="لا تعليقات");var d=b.feed.entry[a].published.$t,k=d.substring(0,4),l=d.substring(5,7),d=d.substring(8,10),m=b.feed.entry[a].title.$t,h=b.feed.entry[a].category[0].term, g=b.feed.entry[a].media$thumbnail.url;-1!=g.indexOf("img.youtube.com")&&(g=b.feed.entry[a].media$thumbnail.url.replace("default","0"));var e=b.feed.entry[a].summary.$t.substring(0,120),n=e.lastIndexOf(" "),e=e.substring(0,n)+"...",c='<div class="wrapper"><div class="rp-fw-img"><a href='+f+'><img src="'+g.replace("/s72-c/","/s150-h90-c/")+'"/></a></div><div class="rp_fwc"><div class="repostt"><a href="/search/label/'+h+'?&max-results=8">'+h+"</a></div><h3><a href="+f+">"+m+'</h3></a><div class="reposth"> '+ [,"يناير","فبراير","مارس","ابريل","مايو","يونيو","يوليو","أغسطس","سيبتمبر","أكتوبر", "نوفمبر","ديسيمبر"][parseInt(l,10)]+" "+d+", "+k+" / <a href="+f+"#comments>"+c+"</a></div><p>"+e+"</p></div></div>";document.write(c)}}; //Recent Gallery Post Widget By Label function rgpost(c){for(var a=0;a<c.feed.entry.length;a++){for(var b=0;b<c.feed.entry[a].link.length;b++)if("alternate"==c.feed.entry[a].link[b].rel){var e=c.feed.entry[a].link[b].href;break}b="thr$total"in c.feed.entry[a]?c.feed.entry[a].thr$total.$t+" تعليقات":"تعليقات معطلة";"1 تعليقات"==b&&(b="1 تعليق");"0 تعليقات"==b&&(b="لا تعليقات");var d=c.feed.entry[a].published.$t,h=d.substring(0,4),k=d.substring(5,7),d=d.substring(8,10),l=c.feed.entry[a].title.$t,g=c.feed.entry[a].category[0].term, f=c.feed.entry[a].media$thumbnail.url;-1!=f.indexOf("img.youtube.com")&&(f=c.feed.entry[a].media$thumbnail.url.replace("default","0"));b='<li class="als-item"><a href='+e+'><img src="'+f.replace("/s72-c/","/s170-h110-c/")+'"/></a><div class="repostt"><a href="/search/label/'+g+'?&max-results=8">'+g+"</a></div><h3><a href="+e+">"+l+'</a></h3><font class="reposth2"> '+[,"يناير","فبراير","مارس","ابريل","مايو","يونيو","يوليو","أغسطس","سيبتمبر","أكتوبر", "نوفمبر","ديسيمبر"][parseInt(k,10)]+" "+ d+", "+h+" / <a href="+e+"#comments>"+b+"</a></font></li>";document.write(b)}}; //Recent Gallery Slider Post Widget By Label Part1 function rpslider(c){for(var a=0;a<c.feed.entry.length;a++){for(var b=0;b<c.feed.entry[a].link.length;b++)if("alternate"==c.feed.entry[a].link[b].rel){var f=c.feed.entry[a].link[b].href;break}b="thr$total"in c.feed.entry[a]?c.feed.entry[a].thr$total.$t+" تعليقات":"تعليقات معطلة";"1 تعليقات"==b&&(b="1 تعليق");"0 تعليقات"==b&&(b="لا تعليقات");var d=c.feed.entry[a].published.$t,h=d.substring(0,4),k=d.substring(5,7),d=d.substring(8,10),l=c.feed.entry[a].title.$t,g=c.feed.entry[a].category[0].term, e=c.feed.entry[a].media$thumbnail.url;-1!=e.indexOf("img.youtube.com")&&(e=c.feed.entry[a].media$thumbnail.url.replace("default","0"));b='<li><img src="'+e.replace("/s72-c/","/s753-h340-c/")+'" class="rpsimg"/><div class="lof-main-item-desc"><h3><a href="/search/label/'+g+'?&max-results=8"><large>'+g+"</large></a><i> \u2014 "+[,"يناير","فبراير","مارس","ابريل","مايو","يونيو","يوليو","أغسطس","سيبتمبر","أكتوبر", "نوفمبر","ديسيمبر"][parseInt(k,10)]+" "+d+", "+h+" / <a href="+f+"#comments><small>"+ b+"</small></a></i></h3><h2><a href="+f+">"+l+"</a></h2></div></li>";document.write(b)}}; //Recent Gallery Slider Post Widget By Label Part2 function rpslider2(c){for(var b=0;b<c.feed.entry.length;b++){for(var a=0;a<c.feed.entry[b].link.length&&"alternate"!=c.feed.entry[b].link[a].rel;a++);a=c.feed.entry[b].media$thumbnail.url;-1!=a.indexOf("img.youtube.com")&&(a=c.feed.entry[b].media$thumbnail.url.replace("default","0"));a='<li><img src="'+a.replace("/s72-c/","/s70-h25-c/")+'"/></li>';document.write(a)}}; //Recent Post Widget Part1 function myrecent(c){for(var b=0;b<c.feed.entry.length;b++){for(var a=0;a<c.feed.entry[b].link.length;a++)if("alternate"==c.feed.entry[b].link[a].rel){var d=c.feed.entry[b].link[a].href;break}var a=c.feed.entry[b].published.$t,f=a.substring(0,4),g=a.substring(5,7),a=a.substring(8,10),e=c.feed.entry[b].category[0].term,h=c.feed.entry[b].title.$t,a='<div class="po_content"><div class="po_img"><a href='+d+'><img src="'+c.feed.entry[b].media$thumbnail.url.replace("/s72-c/","/s110-h85-c/")+'"/></a></div><div class="fea_con"><div class="tune"><a href="/search/label/'+ e+'?&max-results=8">'+e+"</a></div><h3><a href="+d+">"+h+'</a></h3><div class="date-header">'+[,"يناير","فبراير","مارس","ابريل","مايو","يونيو","يوليو","أغسطس","سيبتمبر","أكتوبر", "نوفمبر","ديسيمبر"][parseInt(g,10)]+" "+a+", "+f+"</div></div></div>";document.write(a)}}; //]]> </script> وهده الكود يتم وضعه في التخطيط الكود في التخطيط تابع لاضهار قسم بدون وصف <script src="/feeds/posts/default/-/العاب?published&alt=json-in-script&start-index=1&max-results=4&callback=repostl1"></script> ------------ الكود في التخطيط تابع لاضهار قسم مع الوصف <script src="/feeds/posts/summary/-/العاب?published&alt=json-in-script&start-index=1&max-results=4&callback=repostfw"></script> ------------------ استبدل العاب باسم التسمي أخي الكريم1 نقطة