اذهب إلى المحتوى

لوحة المتصدرين

  1. محمد أحمد العيل

    • نقاط

      4

    • المساهمات

      308


  2. 7865T876G587658 G6T87G6G75

    • نقاط

      4

    • المساهمات

      14


  3. يحيى

    يحيى

    الأعضاء


    • نقاط

      1

    • المساهمات

      565


  4. المبرمج العربي

    • نقاط

      1

    • المساهمات

      245


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 01/27/16 في كل الموقع

  1. توفر الكثير من المواقع واجهات برمجية Application Programming Interface ،API بهدف إتاحة موارد الموقع لتطبيقات خارجية؛ قد تكون تطبيقات ٍللجوال، أجهزةً لوحية، أو أجهزةً مكتبية. قد نود مثلا إنشاء تطبيق للجوال نعرض فيه منتجات الموقع. نستخدم لغة البرمجة المناسبة للتطبيق (جافا مثلا لتطبيقات أندرويد) الذي يرسل طلبات لواجهتنا البرمجية يحصُل بموجبها على بيانات يتولى هو طريقة عرضها. نقول إن تطبيق الجوال في هذه الحالة يستهلك Consume الواجهة البرمجية. هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي: مدخل إلى Laravel 5.تثبيت Laravel وإعداده على كلّ من Windows وUbuntu.أساسيات بناء تطبيق باستخدام Laravel.إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel.نظام Blade للقوالب.تهجير قواعد البيانات في Laravel. استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها. إنشاء سلة مشتريات في Laravel.الاستيثاق في Laravel. إنشاء واجهة لبرمجة التطبيقات API في Laravel. (هذا الدرس)إنشاء مدوّنة باستخدام Laravel.استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel.الدوّال المساعدة المخصّصة في Laravel.استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار. نغطي في هذا الدرس المواضيع التالية: ماهي واجهات REST البرمجية؟الممارسات المنصوح بها في واجهات REST البرمجية.إنشاء واجهة برمجية لمشروع Larashop.ماهي واجهات REST البرمجية؟توصف الكثير من الواجهات البرمجية بأنها RESTful، فما المقصود بهذا الوصف؟ تختصر REST العبارة Representational State Transition (النقل التمثيلي للحالة) وهي طريقة لتصميم البرمجيات تعرِّف معاييرَ يجب على خدمات الويب اتباعها من أجل أداء أعلى وصيانة أسهل. تعتمد بنية التطبيقات REST على بروتوكول HTTP لإرسال الطلبات والحصول على إجابات؛ ومن أهم القيود التي يجب الالتزام بها في تطبيقات REST: العمل حسب مبدأ خادوم-عميل Server-Client، انعدام الحالة Stateless وتوحيد الواجهات (إضافة لقيود أخرى). مبدأ خادوم-عميل: يجب التفريق بين واجهة المستخدم والخادوم الذي يخزن البيانات ويطبق العمليات عليها.انعدام الحالة: يجب أن يحوي الطلب الموجّه من العميل إلى الخادوم كل المعلومات الضرورية ليستطيع الخادوم فهمه والإجابة عليه؛ دون الحاجة لسياق محفوظ على الخادوم (لفهم الطلب).توحيد الواجهات بمعنى أن كل مورد على الخادوم يمكن تعريفه فرديا واستغلاله عبر بيانات تمثله يحتفظ بها العميل. يجب أن تكون الطلبات واضحة يمكن فهمها والإجابة عنها دون الحاجة لمعلومات خارجة عنها. يدخل ضمن توحيد الواجهات أيضا افتراضُ العميل أن أي إجراء Action غيرُ متوفر على الخادوم، ما لم يصّرح هذا الأخير بتوفره.تساهم هذه القيود (والقيود الأخرى التي تعرفها بنية REST) في تسهيل عمل الواجهات، الرفع من أدائها، تيسير الصيانة وقابلية التمدد Scalability. سنرى في الفقرة التالية توصيات لبناء واجهات برمجية تساعد في احترام مبادئ REST. ملحوظة: يكثُر وصف الواجهات البرمجية بأنها RESTful (تلتزم بقيود REST) دون أن تلتزم بكامل القيود التي تعرِّفها بنية REST، وهو ما يجعلها أقرب لواجهات شبيهة لـREST منها لواجهات RESTful. الممارسات المنصوح بها في واجهات REST البرمجيةيُساعد الالتزام بالممارسات التالية في بناء واجهة تطبيقات برمجية ذات أداء عال وقابلية كبيرة للتمدد والصيانة. استخدام إجراءات HTTP لتحديد العمل الذي سيؤديه الخادوم: GET للحصول على مورد، POST لإنشاء مورد جديد، PUT لتحديث مورد وDELETE لحذفه.أَصْدَرَة Versioning الواجهة: يساعد استخدام إصدارات في عدم كسر التطبيقات التي تستهلك الواجهة البرمجية. يحدّد العميل إصدار واجهة التطبيق الذي يود العمل عليه مما يسمح بإحداث تغييرات على الخادوم تضمَّن في إصدار جديد دون أن يتوقف عملاء الواجهة البرمجية.من المتعارف عليه استخدام أسماء جموع لوصف الموارد، api.mysite/v1/products مثلا للمنتجات. ليس واجبا اتباع هذا العرف لكن الأهم هو تناسق تسمية الموارد: لا تخلط بين أسماء مفردة للموارد وجموع.استخدام الإجابات الجزئية: طلب العميل اسم المنتج؟ أرسل اسم المنتج فقط، وليس كامل بيانات المنتج، في الإجابة.استخدام رموز الحالة: تسهّل رموز الحالة في HTTP التخاطب مع العميل. عولج الطلب على النحو الأمثل؟ أرسِل الرمز 200 في الإجابة. طلب العميل إنشاء مورد وتم الأمر؟ أرسل الرمز 201 في الإجابة؛ وهكذا. راجع هذا الرابط للمزيد من رموز الحالة في HTTP.ضع حدًّا أقصى لعدد الطلبات القادمة من نفس عنوان IP في الواجهات المفتوحة للجميع. يساعد هذا الأمر في التصدي للعملاء الذي يفرطون في استخدام واجهة تطبيقاتك البرمجية. ينصح أيضا بحظر عناوين IP ذات السلوك المشبوه حتى لا يؤثر على بقية المستخدمين.قد يُختلف حول هذه التوصية، إلا أنه يُنصح باستخدام صيغة JSON لإرسال البيانات في الإجابة عن الطلب، ما لم يحدّد العميل عكس ذلك.خبِّئ Cache نتائج طلبات GET التي لا تتغير كثيرا. ربما تكون قائمة العلامات التجارية في مواقع التسوق مثالا جيدا للبيانات التي يجب تخبئتها (قد تمضي أشهر دون الحاجة لإضافة علامة تجارية جديدة).واجهة Larashop البرمجيةسننشئ في هذه الفقرة واجهة تطبيقات برمجية لمشروع Larashop. تشتمل الواجهة على المسارات أدناه. تستخدم جميع المسارات إجراء GET للحصول على المورد. التسلسل المورد الرابط الوصف رمز الحالة1Product/api/v1/productsسرد لائحة بالمنتجات وخاصياتها2002Product/api/v1/products/1سرد خاصيات المنتج رقم 12003Category/api/v1/categoriesسرد لائحة بتصنيفات المنتجات2004Category/api/v1/categories/1التصنيف ذو المعرّف 1200لاحظ أننا لم نتح إمكانية التعديل على الموارد عبر الواجهة. تشير v1 في المسارات إلى رقم الإصدار 1. نفتح ملف المسارات routes.php ونعدّله بإضافة المسارات التالية: // API routes... Route::get('/api/v1/products/{id?}', ['middleware' => 'auth.basic', function($id = null) { if ($id == null) { $products = App\Product::all(array('id', 'name', 'price')); } else { $products = App\Product::find($id, array('id', 'name', 'price')); } return Response::json(array( 'error' => false, 'products' => $products, 'status_code' => 200 )); }]); Route::get('/api/v1/categories/{id?}', ['middleware' => 'auth.basic', function($id = null) { if ($id == null) { $categories = App\Category::all(array('id', 'name')); } else { $categories = App\Category::find($id, array('id', 'name')); } return Response::json(array( 'error' => false, 'user' => $categories, 'status_code' => 200 )); }]);يعرف المسار Route::get('/api/v1/products/{id?}', ['middleware' => 'auth.basic', function($id = null)رابطًا يطلب المنتجات مع معرّف اختياري id. يُستخدم المعرف لطلب منتج واحد وفي حال عدم ذكره ترجِع واجهة التطبيقات جميع المنتجات. نحمي المورد بالتعليمة 'middleware' => 'auth.basic' التي تستوثق من العميل. حددنا نمط الاستيثاق بـauth.basic لاستخدام بريد المستخدِم (حقل email في جدول users) مع كلمة السر. يستدعي كل مسار النموذج المناسب للعثور على البيانات في القاعدة ثم نرسل الإجابة بصيغة JSON بالتعليمة Response::json. عند طلب الرابط http://larashop.dev/api/v1/products ستظهر نافذة تطلب إدخال بريد المستخدم وكلمة سره. استخدم الحساب الذي أنشأته في درس الاستيثاق وستظهر النتيجة التالية في المتصفح (بعد التنسيق) { "error":false, "products": [ { "id":"1", "name":"Mini skirt black edition", "price":"35" }, { "id":"2", "name":"T-shirt blue edition", "price":"64" }, { "id":"3", "name":"Sleeveless Colorblock Scuba", "price":"13" } ], "status_code":200 }حصلنا على إجابة بصيغة JSON للطلب الذي أرسلناه من أجل الحصول على منتجات الموقع. يشير الرمز 200 إلى أن معالجة الطلب تمّت دون مشاكل. يمكن للعميل الآن تنسيق الإجابة لعرضها بطريقة مناسبة. خاتمةوضعنا في هذا الدرس أساسا يمكن البناء عليه لإنشاء واجهات برمجية أكثر تطورا. يتلخص إنشاء واجهات برمجية في Laravel في تعريف المسارات، استخدام النماذج للحصول على البيانات المطلوبة ثم تهيئة الإجابة بصيغة JSON ثم إرسالها. ترجمة -وبتصرّف- للمقال Laravel 5 REST API لصاحبه Rodrick Kazembe.
    1 نقطة
  2. يأتي Laravel، وهذه إحدى ميزاته الكثيرة، مضمنّا بآليات استيثاق Authentication جاهزة للاستخدام. سنطبق في هذا الدرس آلية الاستيثاق على صفحة الدفع checkout بحيث يُسمح بالدخول للمستخدمين المسجلين فقط. هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي: مدخل إلى Laravel 5. تثبيت Laravel وإعداده على كلّ من Windows وUbuntu. أساسيات بناء تطبيق باستخدام Laravel. إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel. نظام Blade للقوالب. تهجير قواعد البيانات في Laravel. استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها. إنشاء سلة مشتريات في Laravel. الاستيثاق في Laravel. (هذا الدرس) إنشاء واجهة لبرمجة التطبيقات API في Laravel. إنشاء مدوّنة باستخدام Laravel. استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel. الدوّال المساعدة المخصّصة في Laravel. استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار. يغطي الدرس المواضيع التالية: إعداد الاستيثاق في Laravel 5. أساسيات الاستيثاق في Laravel 5. تغيير رابط تسجيل الدخول المبدئي. إعدادات الاستيثاق في Laravel 5 يوجد ملف إعداد الاستيثاق على المسار config/auth.php. في ما يلي جزء من الملف: 'model' => App\User::class, 'table' => 'users', 'password' => [ 'email' => 'emails.password', 'table' => 'password_resets', 'expire' => 60, ], يحدّد الملف: اسم نموذج الاستيثاق. اسم جدول المستخدمين. خيارات إعادة تعيين كلمة السر. سنستخدم النموذج User لاستيثاق المستخدمين. افتح الملف User.php وعدّله على النحو التالي: <?php namespace App; use Illuminate\Auth\Authenticatable; use Illuminate\Database\Eloquent\Model; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; class User extends Model implements AuthenticatableContract { use Authenticatable; /** * The database table used by the model. * * @var string */ protected $table = 'users'; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = ['name', 'email', 'password']; /** * The attributes excluded from the model's JSON form. * * @var array */ protected $hidden = ['password', 'remember_token']; } فلنعرّج قليلا على الأصناف الجديدة علينا: use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; توجد في Laravel أصناف يطلق عليها اسم العقود Contracts. العقود هي مجموعة واجهات Interfaces تعرّف خدمات يوفّرها إطار العمل. تعرّف العقود دوال يحتاجها إطار العمل لتأدية الخدمة. يستورد السطر أعلاه العقد Authenticatable وهي واجهة تعرّف الدوال الضرورية لاستيثاق المستخدمين. عند استيراد الواجهة أعطيناها الاسم AuthenticatableContract حتى لا تختلط مع السمة Trait الذي يحمل نفس الاسم (نستعمله في نموذج المستخدم كما سنرى لاحقا). يجب على الكائن الذي يستوثق من المستخدمين (نموذج المستخدم في حالتنا) أن ينجز Implement هذه الواجهة: class User extends Model implements AuthenticatableContract لإنجاز دوال الواجهة (تعرّف واجهة Authenticatable الدوال دون أن تنجزها) نستخدم السمة Illuminate\Auth\Authenticatable. نستورده أولا: use Illuminate\Auth\Authenticatable; ثم نستخدمه: use Authenticatable; يحدّد النموذج جدول البيانات المستخدم لتخزين بيانات المسجَّلين، ويفعّل الإسناد الشامل لبعض الحقول. تعيّن مصفوفة hidden$ بيانات المستخدم التي لا نودّ عرضها عند الإجابة على طلب عبر واجهة تطبيقات برمجية API (يجب إخفاء كلمة سر المستخدم password ورمز الأمان remember_token عن الخارج). يأتي مع Laravel مبدئيا ملف تهجير لإنشاء جدول المستخدمين. افتح ملف التهجير 2014_10_12_000000_create_users_table.php (قد يختلف الختم الزمني في اسم الملف حسب إصدار Laravel): <?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('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('password', 60); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('users'); } } يعرّف ملف التهجير حقول جدول المستخدمين. تعيّن الدالة rememberToken رمز حماية لتأمين المستخدمين ضدّ هجمات تزوير الطلب عبر الموقع CSRF. استمارات التسجيل والولوج Login يوجد في عرض الدخول login.blade.php استمارتان، واحدة لتسجيل المستخدمين Registration والأخرى لدخولهم Login. افتح ملف العرض login وحدّثه على النحو التالي: @extends('layouts.layout') @section('content') <section id="form"><!--form--> <div class="container"> <div class="row"> <div class="col-sm-4 col-sm-offset-1"> <div class="login-form"><!--login form--> <h2>Login to your account</h2> <form method="POST" action="{{url('auth/login')}}"> {!! csrf_field() !!} <input type="email" name="email" id="email" placeholder="Email Address" /> <input type="password" name="password" id="password" placeholder="Password" /> <span> <input name="remember" id="remember" type="checkbox" class="checkbox"> Keep me signed in </span> <button type="submit" class="btn btn-default">Login</button> </form> </div><!--/login form--> </div> <div class="col-sm-1"> <h2 class="or">OR</h2> </div> <div class="col-sm-4"> <div class="signup-form"><!--sign up form--> <h2>New User Signup!</h2> <form method="POST" action="{{url('register')}}"> {!! csrf_field() !!} <input type="text" name="name" id="name" placeholder="Name"> <input type="email" name="email" placeholder="Email Address"/> <input type="password" name="password" placeholder="Password"> <button type="submit" class="btn btn-default">Signup</button> </form> </div><!--/sign up form--> </div> </div> </div> </section><!--/form--> @endsection التغييرات الأساسية هنا هي: تعريف رابط مناسب لاستمارتي التسجيل والدخول مع تحديد أن البيانات تُرسَل بإجراء POST: // دخول المستخدمين <form method="POST" action="{{url('auth/login')}}"> // تسجيل المستخدمين <form method="POST" action="{{url('register')}}"> تُرسل بيانات الدخول إلى الرابط larashop.dev/auth/login وبيانات التسجيل إلى الرابط larashop.dev/register. تضيف التعليمة ()csrf_field حقلا أمنيا في الاستمارتين للحيلولة دون هجمات CSRF. مسارات الدخول، الخروج والتسجيل نضيف الآن المسارات الخاصة بالاستيثاق. افتح ملف المسارات routes.php وأضف المسارات التالية: // مسارات الدخول والخروج Route::get('auth/login', 'Front@login'); Route::post('auth/login', 'Front@authenticate'); Route::get('auth/logout', 'Front@logout'); // مسار التسجيل Route::post('/register', 'Front@register'); نعرّف المسار الذي يعرض استمارتي التسجيل والدخول: Route::get('auth/login', 'Front@login'); نعرّف إجراء HTTP POST الذي يوثّق المستخدمين: Route::post('auth/login', 'Front@authenticate'); نعرّف مسار خروج المستخدم: Route::get('auth/logout', 'Front@logout'); نعرف مسار تسجيل المستخدمين الجدد (إجراء HTTP POST): Route::post('/register', 'Front@register'); المسارات المَحمِيّة مسار محمي هو مسار يطلُب من الزائر الدخول قبل الوصول إليه. سنحمي في هذه الفقرة الرابط http://larashop.dev/checkout. يعني هذا أن المستخدمين المسجّلين فقط يمكنهم رؤية صفحة الدفع. عدّل مسار checkout/ في ملف المسارات ليصبح على النحو التالي: Route::get('/checkout', [ 'middleware' => 'auth', 'uses' => 'Front@checkout' ]); تُنفّذ التعليمة 'middleware' => 'auth', قبل دالة Front@checkout؛ وتتحقق من دخول الزائر. فإن لم يكن سجّل دخوله توجّهه إلى الرابط auth/login/، وتعرض له صفحة الدفع بعد الدخول. دوال التسجيل والاستيثاق نعدّل ملف المتحكّم لإضافة دوال تجيب على الطلبات القادمة من المسارات السابقة. افتح ملف المتحكم Front.php لتعديله. نبدأ باستيراد فضاءات الأسماء التي نحتاجها: use App\User; use Illuminate\Support\Facades\Auth; استوردنا نموذج المستخدم User وفضاء الأسماء الخاص بالاستيثاق Auth. توجد في فضاء الأسماء Auth الدوال والكائنات التي نحتاجها للاستيثاق من المستخدمين. تسجيل مستخدم جديد public function register() { if (Request::isMethod('post')) { User::create([ 'name' => Request::get('name'), 'email' => Request::get('email'), 'password' => bcrypt(Request::get('password')), ]); } return Redirect::away('login'); } تستخدم دالة التسجيل المعلومات المذكورة في استمارة التسجيل New User Signup! لإنشاء مستخدم جديد عبر طلب الدالة User::create (تعرّفنا على هذه الدالة خلال درس Eloquent ORM). ثم نوجّه الزائر بعد إلى صفحة الدخول. لاحظ استخدام الدالة bcrypt أثناء تسجيل المستخدم. تعمّي هذه الدالة كلمة السر قبل تخزينها في جدول البيانات. الاستيثاق من المستخدمين تستوثق الدالة التالية من المستخدمين: public function authenticate() { if (Auth::attempt(['email' => Request::get('email'), 'password' => Request::get('password')])) { return redirect()->intended('checkout'); } else { return view('login', array('title' => 'Welcome', 'description' => '', 'page' => 'home')); } } ستوثق الدالة Auth::attempt من المستخدم بناء على عنوان البريد email وكلمة السر password الذين أرسلتهما استمارة الدخول. في حال نجاح دخول المستخدم يُعاد توجيهه إلى صفحة الدفع checkout عبر الدالة ()redirect. تسجيل خروج المستخدمين يؤدي طلب الدالة Auth::logout إلى تسجيل خروج المستخدمين بعد دخولهم عبر الدالة السابقة. عدّل دالة logout الموجودة في ملف المتحكم لتصبح كالتالي: public function logout() { Auth::logout(); return Redirect::away('auth/login'); } تخرج الدالة المستخدم وتوجهه إلى صفحة الدخول. إظهار بيانات الدخول في العرض نحتاج، قبل اختبار التسجيل والدخول، إجراء تغيير أخير. تُظهر الصورة التالية الشريط العلوي الأيمن من الموقع: نريد أن يظهر الشريط على النحو التالي بعد دخول المستخدم: نريد أن يظهر اسم المستخدم بعد الدخول، وإبدال رابط Login بـLogout. افتح ملف العرض layout.blade.php للتعديل عليه. تذكر أن هذا هو العرض الرئيس الذي تمدّده بقية العروض. نغيّر جزئية الترويسة (header) من ملف العرض لتصبح كالتالي: <header id="header"><!--header--> <div class="header_top"><!--header_top--> <div class="container"> <div class="row"> <div class="col-sm-6"> <div class="contactinfo"> <ul class="nav nav-pills"> <li><a href="#"><i class="fa fa-phone"></i> +2 95 01 88 821</a></li> <li><a href="#"><i class="fa fa-envelope"></i> info@domain.com</a></li> </ul> </div> </div> <div class="col-sm-6"> <div class="social-icons pull-right"> <ul class="nav navbar-nav"> <li><a href="#"><i class="fa fa-facebook"></i></a></li> <li><a href="#"><i class="fa fa-twitter"></i></a></li> <li><a href="#"><i class="fa fa-linkedin"></i></a></li> <li><a href="#"><i class="fa fa-dribbble"></i></a></li> <li><a href="#"><i class="fa fa-google-plus"></i></a></li> </ul> </div> </div> </div> </div> </div><!--/header_top--> <div class="header-middle"><!--header-middle--> <div class="container"> <div class="row"> <div class="col-sm-4"> <div class="logo pull-left"> <a href="{{url('')}}"><img src="{{asset('images/home/logo.png')}}" alt="" /></a> </div> </div> <div class="col-sm-8"> <div class="shop-menu pull-right"> <ul class="nav navbar-nav"> <li><a href="#"><i class="fa fa-user"></i> {{Auth::check() ? Auth::user()->name : 'Account'}}</a></li> <li><a href="{{url('checkout')}}"><i class="fa fa-crosshairs"></i> Checkout</a></li> <li><a href="{{url('cart')}}"><i class="fa fa-shopping-cart"></i> Cart</a></li> <li><a href="{{Auth::check() ? url('auth/logout') : url('auth/login')}}"><i class="fa fa-lock"></i> {{Auth::check() ? 'Logout' : 'Login'}}</a></li> </ul> </div> </div> </div> </div> </div><!--/header-middle--> <div class="header-bottom"><!--header-bottom--> <div class="container"> <div class="row"> <div class="col-sm-9"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <div class="mainmenu pull-left"> <ul class="nav navbar-nav collapse navbar-collapse"> <li><a href="{{url('')}}" {{$page == 'home' ? 'class=active' : ''}}>Home</a></li> <li><a href="{{url('products')}}" {{$page == 'products' ? 'class=active' : ''}}>Products</a></li> <li><a href="{{url('blog')}}" {{$page == 'blog' ? 'class=active' : ''}}>Blog</a></li> <li><a href="{{url('contact-us')}}" {{$page == 'contact_us' ? 'class=active' : ''}}>Contact Us</a></li> </ul> </div> </div> <div class="col-sm-3"> <div class="search_box pull-right"> <input type="text" placeholder="Search"/> </div> </div> </div> </div> </div><!--/header-bottom--> </header><!--/header--> أضفنا التغييرين التاليين على ترويسة العرض: إبدال Account بالتعليمة: {{Auth::check() ? Auth::user()->name : ‘Account’}} نستعمل الدالة Auth::check للتحقق من دخول المستخدم؛ في حال الإيجاب نظهر اسمه بالدالة Auth::user وإلا نبقي على عبارة Account. نفس المبدأ مع عبارة Login التي تصبح بعد الدخول Logout، وتغيير الرابط بما يُناسب (larashop.dev/auth/login للدخول وlarashop.dev/logout للخروج). افتح الرابط http://larashop.dev/auth/login وسجل مستخدما جديد عبر الاستمارة New User Signup. بالضغط على زر Signup تستدعي المسار http://laravel.dev/register مع الإجراء POST. تتولى دالة register في المتحكم تلقي الطلب واستدعاء النموذج الذي ينشئ تسجيلة جديدة في جدول البيانات ثم تعيد الدالة توجيه المستخدم إلى صفحة الدخول. يمكنك التأكد من إنشاء المستخدم في الجدول users ضمن قاعدة البيانات. نجرّب الدخول بالمستخدم الجديد بإدخال عنوانه البريدي وكلمة السر في استمارة التسجيل. إن أدخل بيانات مستخدم صالحة فستُنقل إلى صفحة الدفع. لاحظ أن اسم المستخدم وعبارة Logout يظهران في الشريط العلوي. ترجمة -وبتصرّف- للمقال Laravel 5 Authentication لصاحبه Rodrick Kazembe.
    1 نقطة
  3. تعرّفنا في الدّرس السّابق على لغة روبي ووميزاتها. في هذا الدّرس سوف نستعرض بعض أنواع البيانات في Ruby، وسنتعرّف باستفاضة على نوع السلاسل. كما سنتعرّف على أحد أهمّ سمات أيّ لغة برمجة، ألا وهي المتغيّرات. سنستخدم في الجزء الأول من الدّرس سطر أوامر روبي التفاعليّ. افتح الطرفيّة وابدأ جلسة irb عن طريق كتابة أمر irb والضغط على زر Enter. القيم والأنواع القيمة هي أبسط شيء يتعامل معه البرنامج مثل حرف أو رقم. تعرّفنا في الدّرس السّابق على بعض تلك القيم. تختلف القيمة 2 عن القيمة "Hello World"، حيث أن الأولى هي عدد صحيح Integer أمّا الثّانية فهي من نوع سلسلة String، جاءت التسمية من كونها سلسلة من الأحرف. يمكنك التعرّف بسهولة على السلاسل من خلال علامات الاقتباس المحيطة بالقيمة. هناك نوع آخر يسمّى Float وهو أيّ رقم يحتوي على علامة عشريّة، مثلاً: 2.5، 13.6، 4.0. ملحوظة: قد تعتقد أن "12" و"1.5" هي أرقام وتتعامل معها في برنامجك على ذلك فتنفّذ عليها عمليّات حسابيّة وتكتشف بعد ذلك أنّ مفسّر روبي يظهر لك علّة برمجية Bug. سبب ذلك أنّها ربّما تكون أرقامًا بالنسبة لك ولكن المفسّر يعتبرها سلاسل نصيّة حيث أنّها محاطة بعلامات الاقتباس والمفسّر مُبَرْمَج على تصنيف أيّ شيء بين علامات اقتباس على أنّه سلسلة. تريد التأكد من ذلك بنفسك؟ جرّب جمع "12" + "1.5". أو بطريقة أخرى يمكنك استخدام الدّالة المدمجة is_a لسؤال روبي هل هذه القيمة نوعها Integer مثلاً وستردّ عليك روبي true أو false. فمثلاً إذا أردت التأكّد من نوع قيمة معيّنة مثل 12 اكتب الأمر التالي: 12.is_a?(Integer) الآن للعودة إلى ما إذا كان كل من "12" و"1.5” أرقامًا أم سلاسل، جرّب الأوامر التالية (تأكّد من كتابة أوّل حرف بشكل كبير Capital): "12".is_a?(Integer) "1.5".is_a?(Float) أحيانًا عند كتابة أعداد كبيرة قد تجد نفسك محتاجًا إلى إرفاق فواصل لجعل العدد قابلاً للقراءة أكثر، مثلاً 1,000,000. لو فعلت ذلك في روبي ستحصل على خطأ. ولكن يمكنك فعل ذلك مع الأمر puts. مثلاً يمكن كتابة: puts 1,000,000 ماذا كانت النتيجة؟ لم تتوقعها أليس كذلك؟ قامت روبي قامت بطباعة: 1 0 0 رقم 1 و 0 و 0 في أسطر مختلفة. حدث ذلك لأنّ روبي قد فسّرت هذا العدد على أنّه ثلاثة أرقام مستقلّة ومفصول بينها بفواصل. في روبي يمكن استخدام الأمر puts لطباعة أكثر من قيمة في أكثر من سطر عن طريق الفصل بين تلك القيم بفاصلة. فمثلاً لو أردت طباعة "Hello" في سطر وبعدها "World" في سطر باستخدام أمر روبي واحد يمكن استخدام الأمر التالي: puts "Hello", "World" Hello World السلاسل السلاسل في روبي هي مجموعات من الأحرف. يمكن إنشاء سلسلة نصيّة عن طريق كتابة أحرف ونصوص داخل علامتي اقتباس مزدوجة. مثلاً لكتابة سلسلة تحتوي على نصّ Hello Ruby اكتب الأمر التّالي: "Hello Ruby" يمكن استخدام علامة الاقتباس المفردة أيضًا لإنشاء سلسلة في روبي، لذلك فيمكن إنشاء السلسلة السّابقة كالتّالي: 'Hello Ruby' إذا أردت استخدام أحد نوعي علامات الاقتباس في داخل نصّك فعليك استخدام النّوع الآخر لإنشاء السلسلة فمثلا لو أردت إنشاء سلسلة نصيّة بها I'm learning Ruby، واستخدمت علامة الاقتباس المفردة لإنشاء السلسلة سيؤدّي ذلك إلى حدوث خطأ ولن يتمّ تنفيذ الأمر. لذلك فالطريقة الصحيحة لكتابة هذه السلسلة هو استخدام علامة الاقتباس المزدوجة: "I'm learning Ruby" مثال آخر: puts '"Never memorize something that you can look up." -Albert Einstein' خيار آخر لاستخدام علامات الاقتباس في السلاسل يسمّى هروب علامة الاقتباس escaping، يحدث هذا عن طريق وضع خط مائل عكسي Backslash قبل علامة الاقتباس والذي سيؤدّي إلى اعتبارها حرفًا عاديًّا بدلاً من تنفيذها كوسيلة لإنشاء سلسلة. يمكن إذًا كتابة السلسلتين السّابقتين كالتّالي: 'I\'m learning Ruby" "\"Never memorize something that you can look up.\" -Albert Einstein" ذكرنا في الدّرس الأوّل أنّ كل شيء في روبي هو كائن Object. يمكن للكائنات تنفيذ أفعال يُطلق عليها اسم دوال. هناك الكثير من الطرق لجعل كائن ينفّذ دالّة ولكن الطريقة الأكثر شيوعًا هي التنويت النُقطي Dot Notation وهو عبارة عن أن تكتب الكائن (في مثالنا هذا الكائن هو السلسلة "Hello Ruby") متبوع بنقطة ثم اسم الدّالة التي تريد استدعاءها. لنجرّب استدعاء الدّالة length والتي هي دالّة مدمجة في روبي تقوم بإرجاع طول السلسلة أو بمعنى آخر عدد الأحرف الموجودة في السلسلة: "Hello Ruby".length المتغيرات أحد أقوى السمات في أيّ لغة برمجة هي القدرة على التعامل مع المتغيّرات. المتغيّر ببساطة هو عنوان (أو "اسم") يشير إلى قيمة معيّنة. بمعنى آخر فالمتغيّر هو طريقة لحفظ الكائنات في الذّاكرة من أجل الاستخدام لاحقًا. يمكن في روبي تعيين متغيّر إلى كائن بسهولة باستخدام عامل التساوي (Equals Operator =): name = "Sara" في هذا المثال، اسم المتغيّر يشير إلى السلسلة "Sara". يعني هذا أنّه بإمكاننا استدعاء دوال مختلفة مباشرةً على اسم المتغيّر بدلاً من كتابة السلسلة في كلّ مرة أردنا استدعاء دالّة. الآن إذا أردت استدعاء الدّالة length لحساب طول السلسلة يمكن ببساطة كتابة ذلك كالتّالي: name.length لنجرّب الآن بعض دوّال روبي التي يمكن استخدامها مع السّلاسل في روبي (السّلاسل عبارة عن كائنات في روبي) على هذا المتغيّر. على سبيل المثال، دالّة reverse ستقوم بطباعة السلسلة معكوسة: name.reverse دوال upcase و downcase من الدوال الخاصّة بالسلاسل أيضًا دالّتا upcase و downcase. تقوم دالّة upcase بتحويل كل الأحرف الموجودة في السلسلة النصيّة إلى أحرف كبيرة Capital Letters. أمّا دالّة downcase فتحوّل كل الأحرف الموجودة في السلسلة إلى أحرف صغيرة Small Letters. جرّب استدعاء الدّالتين على المتغيّر name: name.upcase name.downcase هناك عدد كبير جدًا من الدوال الخاصّة بالسلاسل يمكنك التعرّف على جميعها عن طريق استخدام دالّة methods (نعم هذا هو اسمها) على المتغيّر الخاصّ بك، هكذا: name.methods عند تنفيذ الأمر ستقوم روبي بعرض جميع الدوال المختلفة التي يمكن لهذا النوع من الكائنات استخدامها. يمكنك أيضًا معرفة أكثر عن تلك الدوال عن طريق قراءة التوثيقات الخاصّة بها. دوال Bang ربّما لاحظت أن جميع الدوال التي استخدمناها حتّى الآن لم تغيّر شيئًا في السلسلة، فمثلاً إذا أردتُ معرفة القيمة الموجودة في المتغيّر name من جديد سأجد أن القيمة ما زالت كما عيّنتها من البداية (لمعرفة قيمة متغيّرك فقط اكتب اسم المتغيّر واضغط Enter أو استخدم puts إن أردت). لم تتغيّر القيمة وتصبح السلسلة معكوسة ولا جميع الحروف كبيرة أو صغيرة. لكن ماذا لو أردت فعلاً تغيير تلك القيمة؟ سنجرّب بعض الدوال التي تقوم بالفعل بتغيير قيمة السلسلة. أنشئ متغيّرًا باسم fruit واجعله يساوي السلسلة "apple". يمكن تغيير قيمة ذلك المتغيّر عن طريق استدعاء دوال تسمّى بدوال Bang، تنتهي تلك الدوال بعلامة التعجّب أو ما يسمّى برمز Bang. فمثلاً لو أردت تنفيذ الدالة reverse على السلسلة الخاصّة بك وحفظ القيمة الجديدة بدلاً من القيمة الأصليّة يمكن كتابة ذلك ببساطة هكذا: fruit.reverse! عندما نقوم بطباعة المتغيّر بعد ذلك نلاحظ تغيّر القيمة إلى elppa بدلاً من القيمة السّابقة apple. بهذا نكون قد استغنينا تمامًا عن القيمة الأصليّة واستبدلناها بالقيمة الحاليّة. معظم الدوال الخاصّة بالسلاسل لديها دالّة Bang مماثلة. على سبيل المثال هناك أيضًا دالّة Bang مقابلة لدالّة upcase العاديّة. إذًا فيمكننا كتابة: fruit.upcase! سيطبع هذا الأمر قيمة السلسلة بأحرف كبيرة وأيضًا من جديد سيتمّ استبدال القيمة السابقة بالقيمة الجديدة والتي هي ELPPA. إذا كانت هناك علامة تعجّب Bang في نهاية دالّة روبي فهذا غالبًا يعني كن حذرًا، يمكن لهذه الدالّة أن تكون خطرًا. في حالة الأمثلة السّابقة فهي تعني أنّ قيمة السلسلة ستتغيّر فيجب أن تكون حذرًا متى قمت باستخدام هذه الدوال. تسلسل الدوال قد يكون راودك تساؤل حول ماذا لو أردت تنفيذ العديد من الدوال على أحد المتغيّرات، هل يجب كتابة استدعاء الدالّة على المتغيّر لكل دالّة على حدة؟ لحسن الحظّ يمكن استدعاء أكثر من دالة في وقتٍ واحد على نفس المتغيّر. على سبيل المثال إذا عدنا من جديد إلى المتغيّر name وأردنا كتابته معكوسًا وبأحرف كبيرة، يمكن كتابة ذلك تسلسليًّا هكذا: name.reverse.upcase ولكن تذكّر دائمًا أنّه يتمّ تنفيذ الدوال بالترتيب من اليسار إلى اليمين. رغمّ أنّها لا تهمّ في حالة المثال أعلاه، فحتى إذا بدّلنا الترتيب ستكون النتيجة مشابهة. إلا أنّه يمكن أن يتغيّر النّاتج عن النّاتج الذي تتوقعه في حالات أخرى، لذلك يجب التحقّق من الترتيب عند استخدام هذه الطريقة في استدعاء الدوال. إدراج شيفرات برمجية في السلاسل يمكن بطريقة بسيطة جدًا إدراج شيفرات برمجيّة في سلاسل نصيّة وتنفيذ تلك الشيفرات. يمكن فعل ذلك عن طريق وضع الشيفرات البرمجيّة داخل حاضنات Curly Brackets مع إضافة رمز التلبيد Hash في البداية: "Hello my name is #{name}" يطبع هذا نصًا يحتوي على الجملة المكتوبة بالإضافة إلى النصّ الموجود في المتغيّر name الذي قمنا بإنشائه سابقًا. لذلك فالسلسلة السابقة ستصبح "Hello my name is Sara". ما حدث هو أنّه قد تمّ إدراج قيمة المتغيّر name بداخل السلسلة حيث أنّ علامة التلبيد مع الحاضنات تخبر روبي بأن الموجود بينها هو شيفرات يجب على روبي تنفيذها أولاً وليس طباعتها كما هي. هناك أمر مهمّ عليك تذكّره وهو أنّه عند استخدام شيفرات برمجيّة بداخل سلسلة فلا بد من استخدام علامات الاقتباس المزدوجة. إذا استخدمت علامات اقتباس مفردة فسيتمّ طباعة النصّ كما هو {Hello my name is \#{name. والخط المائل هذا يعني أنّه قد تمّ تخطي هذه القيمة وطُبعت كما هي، مثلما رأينا في السّابق مع 'I\'m'. تطبيق عملي الآن بعد التعرّف على المتغيّرات والسلاسل حان الوقت لكتابة برنامج حقيقي باستخدامهما. في هذا البرنامج سيتمّ طباعة سلسلة نصيّة تسأل المستخدم عن اسمه، ثمّ يقوم البرنامج بعد ذلك باستخدام الاسم الذي سيدخله المستخدم لتطبيق بعض الدوال التي تطرّقنا إليها. أوّلاً نحتاج لإنشاء ملفّ روبي، سمّه ما تريد ولكن لا تنس إضافة rb. إلى نهاية اسم الملفّ. لقد أسميتُ ملفّي greetings.rb. بدايةً سنحتاج إلى طباعة رسالة للمستخدم لسؤاله عن اسمه. لفعل ذلك سنستخدم الأمر puts: puts "Hello, what's your name?" بعد ذلك سنحتاج إلى تمكين المستخدم من كتابة اسمه. أمر gets أمر gets هو اختصار لـ get string والذي يقوم بإيقاف البرنامج وانتظار عمليّة إدخال من المستخدم قبل متابعة تنفيذ البرنامج. سيكون المُدخَل عبارة عن سلسلة كما هو واضح من اسم الأمر. إحدى دوال السلاسل دالّة تسمّى chomp يمكن تطبيقها على سلسلة لحذف الحرف الذي يتمّ إضافته افتراضيًّا للسلسلة بعد الضغط على Enter، حيث أنّه عند استقبال إدخال من المستخدم وبضغطه على زرّ Enter يتمّ تلقائيًّا إضافة حرف سطر جديد إلى نهاية السلسلة. إذًا لتمكين المستخدم من إدخال اسمه نحتاج إلى استخدام أمر gets للحصول على المدخل واستدعاء دالّة chomp لحذف الحرف الزائد وحفظ ناتج ذلك في متغيّر لاستخدامه في وقتٍ لاحق. نكتب ذلك في روبي كالآتي: name = gets.chomp وأخيرًا سنقوم بكتابة شيفرات برمجيّة تتعامل مع هذا المدخل وتطبع بعض المعلومات عنه، أضف ما يلي بعد الأمرين السّابقين في ملفّ روبي الخاصّ بك: puts "Hello #{name}. Your name's length is #{name.length}. That's not really long! Your name backwards is #{name.reverse.downcase.capitalize}" ليُصبح كامل الملف على النّحو التّالي: puts "Hello, what's your name?" name = gets.chomp puts "Hello #{name}. Your name's length is #{name.length}. That's not really long! Your name backwards is #{name.reverse.downcase.capitalize}" يقوم هذا الأمر بطباعة سلسلة نصيّة تحتوي على شيفرات برمجيّة تطبع اسم المستخدم، عدد الأحرف في اسم المستخدم واسم المستخدم معكوسًا. لاحظ في الجزء الثالث كيف أضفنا تسلسل دوال من ثلاث دوال، إحداها هي دالّة جديدة تسمّى capitalize. تقوم دالّة capitalize بتغيير الحرف الأوّل فقط من السلسلة وتحويله إلى حرف كبير على عكس دالة upcase التي تحوّل جميع أحرف السلسلة. احفظ الملفّ بعد كتابة الشيفرات البرمجيّة كاملة ثم قم بتنفيذه عن طريق فتح الطرفيّة والتوجّه إلى مسار المجلّد الذي قمت بحفظ الملفّ به ثم كتابة ruby متبوعًا باسم الملف (أي أنه في حالتي سأكتب الأمر ruby greetings.rb)، إذا واجهتك مشكلة في ذلك فراجع كيف قمنا بعمل ذلك في الدّرس الأوّل. خاتمة بهذا نكون قد انتهينا من الدّرس الثاني وتعرفنا على بعض المفاهيم الأساسيّة في روبي. جاء دورك للتطبيق وحدك، قارن ما يفعله البرنامج بالشيفرات البرمجيّة الخاصّة به للتعرّف أكتر على وظيفة كل جزء. طبّق أيضًا استخدام دوال أخرى لم نستخدمها في البرنامج. كذلك ربّما تريد تجربة كتابة اسمك ثنائيًّا أو ثلاثيًّا مع إضافة مسافة بين كل اسم، هل يتمّ حساب المسافة كحرف ضمن الاسم؟ ابحث في الدوال الخاصّة بالسلاسل عن سلسلة تعالج هذا الأمر وطبّقها.
    1 نقطة
  4. إنَّ تقنية الصور والأفلام ثلاثية الأبعاد التي تعتمد على الظلال الحمراء والزرقاء قديمة مقارنة بالجيل الجديد من أفلام 3D التي انتشرت مؤخرًا إلا أنها كانت جيدة وكان الناس يرغبون بها. فقررت أن أكتب هذا الدرس عن كيفية تصميم صور بارزة حقيقية تعمل بشكل صحيح باستخدام هذه التقنية، وبحثت في عِلم تجسيم الصور لإيجاد طريقة لجعل الصور تخرج من الشاشة. لنبدأ بهذا الدرس لتَعلُّم استخدام هذه التقنية القديمة لإنشاء هذا النوع من الصور ثلاثي الأبعاد في برنامج فوتوشوب. حتى نستطيع متابعة هذا الدرس بشكل صحيح ونستطيع رؤية الصور بهذا التأثير ستحتاج إلى نظارات 3D مع العدسات الحمراء والزرقاء. يمكنك الحصول على واحدة من أحد المتاجر أو من التسوق عبر الإنترنت مقابل بضعة دولارات وهي تعمل بشكل ممتاز. أو يمكنكم صناعة واحدة يدويًّا إذا توفرت المواد المُلائمة لديكم من خلال تطبيق التصميم في الصورة التالية. يمكن إنشاء صور ثلاثية الأبعاد بارزة عبر طريقتين. التقنية الأولى هي جمع صورتين منفصلتين من الكاميرا والنتائج في بعض الصور رائعة. التقنية الثانية تُنتج التأثير من صورة واحدة، ما يجعلها مفيدةً بشكل خاص للرسومات، أو أي صورة لم تُلتقط في وضعية ستِريو. إنشاء الصور البارزة من صورتينإنّ تقنية الصورتين تساعد فعلًا على فهم المبدأ خلف تجسيم الصور. يتم إنشاء بروز الصورة من جمع صورتين من زوايا مختلفة، بطريقة مشابهة لعمل العينين. جرّب النظر إلى شيء قريب منك ودقّق النظر فيه ثم أغلق عينًا واحدة ثم افتحها وأغلق الأخرى. ستلاحظ أن هذا الشيء يبدو وكأنه يتحرك باستدارة معينة (جرّب الاستمرار في تبديل فتح عين واحدة وستلاحظ ذلك بوضوح)، هذه التقنية تستخدم ذات القاعدة. سيتم أخذ صورتين، إمّا باستخدام كاميرتين مربوطتين معًا على مسافة محدّدة، أو من كاميرا واحدة متحركة على منصب ثلاثي القوائم. التقط بضعة صور على بعد بضعة إنشات قريبة من الصورة الأولى أو بضعة أقدام للمناظر البعيدة. افتح الصورتين في فوتوشوب. هذه صورتين منفصلتين جاهزتين للتجسيم من موقع Shutterstock. حدّد الكل CMD+A وانسخ CMD+C صورة ثم ألصقها CMD+V فوق الصورة الأخرى. انقر نقرًا مزدوجًا على الخلفية لتحويلها إلى طبقة عادية. تذكّر أي صورة هي اليسرى وأيهما اليمنى. امنح الطبقات أسماءً بناءً على ذلك. انقر مرتين على الطبقة اليسرى لفتح أنماط الطبقة. ألغِ تفعيل القناة الحمراء واضغط موافق. افتح أنماط الطبقة اليمنى وألغِ تفعيل القناتين الخضراء والزرقاء. ستشاهد تأثيرات بروز الصورة مباشرة بعد ذلك. حرّك الطبقة لمحاذاة صور الإزاحة الملونة على النقطة البؤرية في المقدمة والخلفية لتنعيم الصورة وذلك للحد من مشاكل الرؤية المزدوجة. استخدم أداة القص Crop tool لقص المستند ضمن منطقة تداخل الطبقتين. يتم إنشاء عمق المشهد تلقائيًّا من نقطة تحويل النظر بين الصورتين. المثير في هذه التقنية هو أنك لن تعرف كيف سيكون التأثير المطبّق حتى تنتهي من معالجة الصور وهو ما يحقق متعة التصوير. إنشاء الصور البارزة من صورة واحدةلا يزال ممكنًا إنشاء صور بارزة من صورة واحدة. هذه التقنية تحتاج عملًا إضافيًّا في فوتوشوب ولكنها تمنح مزيدًا من السيطرة على التأثير النهائي. فهي تستخدم خريطة العمق مع فلتر Displace لجعل الصورة تخرج من مكانها وبالتالي خلق تأثير 3D المطلوب. افتح الصورة في فوتوشوب. سنحتاج أولًا إلى إنشاء خريطة العمق، التي تستخدم درجات ألوان الأسود والأبيض لتحديد مدى بُعد كل جزء من الصورة. أنشئ طبقةً جديدةً ثم ارسم تحديدًا مستطيلًا رفيعًا ولوّنه بتدرج لوني من الأسود للأبيض. سيكون هذا المستطيل مرجعًا هامًّا للدرجات اللونية. سنبدأ أولًا بالمنطقة الأقرب للكاميرا. أنشئ طبقة جديدة وحدّد العناصر في المقدمة باستخدام أداة تحديد المضلعات Polygonal lasso tool أو باستخدام أداة القلم Pen tool ثم لّون هذه المنطقة المحدّدة بالأبيض. ضع هدفَ أداة الفرشاة Brush Tool على Highlights وخفّف opacity إلى 50%. لوّن المناطق البيضاء الأبعد بقليل بفرشاة ناعمة بلون رمادي فاتح. سينعكس هذا التغيير في التدرج اللوني على التدرج في العمق. أنشئ طبقة جديدة واجعلها تحت الطبقة البيضاء. حدّد العناصر الأبعد بدرجة من المناطق البيضاء. استخدم تدرج لوني بألوان رمادية متوسطة لتلوين هذه الطبقة بحيث ستكون الأجزاء الأبعد داكنة أكثر والأقرب ستكون فاتحة أكثر. كرّر العملية بإنشاء طبقة جديدة وجعلها خلف الطبقة السابقة وتحديد العناصر الأبعد في كل مرة ومن ثم استخدام تدرج لوني داكن أكثر في كل مرة لتلوين الطبقة، هذه العملية لها تأثير كبير عند النظر إلى النتيجة النهائية باستخدام نظارات الرؤية ثلاثية الأبعاد. الطبقة الأخيرة والتي ستكون أسفل كل الطبقات أي أنها ستظهر خلف جميع الطبقات يجب أن تكون باللون الأسود الصافي وهي ستكون فقط للمناطق الأبعد من الصورة. اضغط CMD+A لتحديد الكل ثم CMD+Shift+C لنسخها مدمجة. اضغط CMD+V للصق الصورة المدمجة فوق طبقات لوحة الطبقات ثم طبّق فلتر التمويه Gaussian Blur بقيمة 10px. هذا التمويه سيخفف قسوة وحِدّة الحواف بعد تطبيق displace على الصورة. احفظ الملف بصيغة PSD. وليكن اسمه "displace.psd". افتح الصورة الأصلية مجددًا ثم استخدم الاختصار CMD+Shift+U لتشبيع الصورة. (إنّ التشبيع هو أمر اختياري ولكنه يضيف نمط القِدَم على تأثير بروز الصورة). اضغط CMD+J لمضاعفة الطبقة ثم انقر مرتين على الخلفية لتحويلها إلى طبقة عادية. انقر مرتين على الطبقة العلوية لفتح نافذة أنماط الطبقة. ألغِ تفعيل القناة الحمراء ثم اضغط موافق. افتح أنماط الطبقة للطبقة الثانية وألغِ تفعيل القناتين الخضراء والزرقاء. على عكس التقنية السابقة فلن تشاهد أي تغيير هنا بعد. حدّد الطبقة العلوية ثم اذهب للقائمة: Filter > Distort > Displace وأدخل القيمة 10px في الخانة الأفقية وقيمة 0 للخانة العمودية ثم اختر الملف displace.psd. سيتم عرض الطبقة وفقًا لخريطة العمق البيضاء والسوداء. ضع نظارات الرؤية ثلاثية الأبعاد لمشاهدة بُعد تجويف الخلفية. حرّك الطبقة العلوية لمحاذاة الصور في النقطة البؤرية للحد من مشاكل الرؤية المزدوجة، ثم قص الصورة بالحجم المناسب. الفائدة من هذه التقنية هي أن تمتلك القدرة على السيطرة الكاملة للتلاعب بالصورة. وبعد أن وضعنا الطبقة في خريطة العمق داخل ملف displace يمكننا العودة دائمًا إلى هذا الملف وإعادة ضبط وتعديل الدرجات اللونية والتمويه لتغيير التأثير ثلاثي الأبعاد. ترجمة -وبتصرّف- للمقال: How To Create Anaglyph 3D Images That Really Work لصاحبه: Chris Spooner.
    1 نقطة
  5. تحتاج أغلب الشركات العاملة على الشبكة للانطلاق في التسويق بالمحتوى. يُعرَّف التسويق بالمحتوى بأنه "مقاربة تسويق ترتكز على إنتاج محتوى جيد، مناسب وذي قيمة ثم توزيعه من أجل جذب فئة محدّدة بدقة والحفاظ عليها، وفي آخر المطاف الحصول على إجراء ذي مردود ربحي من الزبون". هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي: مدخل إلى Laravel 5.تثبيت Laravel وإعداده على كلّ من Windows وUbuntu.أساسيات بناء تطبيق باستخدام Laravel.إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel.نظام Blade للقوالب.تهجير قواعد البيانات في Laravel. استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها. إنشاء سلة مشتريات في Laravel.الاستيثاق في Laravel. إنشاء واجهة لبرمجة التطبيقات API في Laravel.إنشاء مدوّنة باستخدام Laravel. (هذا الدرس)استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel.الدوّال المساعدة المخصّصة في Laravel.استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار. نفرض مثلا أنك طورت مشروع Larashop لبيع الملابس على الشبكة. يقوم مبدأ التسويق عبر المحتوى على التأسيس لنفسك بوصفك خبيرا في المجال، فتكتُب - مثلا - عن الملابس وكيفية اختيارها والحفاظ عليها وتقدم نصائح لزوار موقعك؛ مما يرفع من احتمالات الشراء من متجرك، وهو ما يمثل قيمة تجارية للموقع. تعمل مدونات المؤسسات على تنفيذ هذا المبدأ فتنشر محتوى مناسبا لجمهورها مما يكون له الأثر الإيجابي على المؤسسة أو الشركة. لا يقتصر المحتوى المنشور في المدونة على المحتوى الكتابي بل يتعداه للمرئي مثل مقاطع الفيديو، الصوتيات والصور. يغطي الدرس المواضيع التالية: أهم خاصيات المدونةالمنشورالتصنيفاتالوسوم Tagsعوامل التحسين لمحركات البحثعنوان المنشوروصف Metaدور الشبكات الاجتماعيةتهجيرات قاعدة البيانات الخاصة بمدونة Larashop.خصائص المدونةنذكر في هذه الفقرة الخصائص التي نريد تواجدها في مدونتنا. المنشورات Postsيتمثل المحتوى الأساسي للمدونة في المنشورات، إذ تحوي المعلومات التي نريد نشرها. سنحصُل على المنشورات من قاعدة البيانات وسنستخدم HTML لتهيئتها. التصنيفاتتُستخدَم التصنيفات لتجميع المنشورات ذات القاسم المشترك. مثلا يمكن أن تنشئ تصنيفا لملابس الرجال، آخر للملابس النسائية وثالث لملابس الأطفال وهكذا. الوسومتشبه الوسوم التصنيفات، إلا أنها أكثر تخصيصا. يمكنك مثلا إنشاء وسم للملابس الشتوية ثم وضعه على جميع المنشورات بغض النظر عن تصنيفها. يمكن للمنشور الواحد أن يرتبط بأكثر من وسم؛ يمكن أن تضيف للمنشور وسما بنوعية القماش المستخدم، وآخر للفصل المناسب لارتدائه. عوامل التحسين لمحركات البحثلا نريد لمنشوراتنا أن تظهر في آخر صفحة من مليون نتيجة في محركات البحث، سيكون جيدا أن نظهر في الصفحة الأولى لذا يجب الاهتمام بالتحسين لمحركات البحث، راجع مقال إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel 5. بالنسبة لمدونتنا فسنهتم بالعاملين: عنوان المنشور، وهو العنوان الذي سيظهر في محركات البحث، يُستحسن ألا يتعدى 56 محرفا.وصف Meta، يظهر تحت العنوان في نتيجة محركات البحث. من الأفضل ألا يتعدى 160 محرفا.التهجيرات الخاصة بمنشورات مدونة Larashopحان الآن وقت التنفيذ. في ما يلي جداول قاعدة البيانات التي نحتاج لإنشائها للمدونة. الحقول التالية مشتركة بين جميع الجداول التسلسل الحقل نوع البيانات الوصف1created_atTimestampختم زمني لوقت إنشاء التسجيلة2updated_atTimestampختم زمني لوقت تحديث التسجيلةجدول تصنيفات المدونةالتسلسل الحقل نوع البيانات الوصف1idINTمعرّف التصنيف، مفتاح رئيس2categoryVARCHARاسم التصنيفجدول وسوم المدونةالتسلسل الحقل نوع البيانات الوصف1idINTمعرّف الوسم مفتاح رئيس2tagVARCHARاسم الوسمجدول الوسوم والمنشورات: بما أنه يمكن أن يكون للمنشور أكثر من وسم، فيجب إنشاء جدول خاص للربط بين الوسم والمنشور.التسلسل الحقل نوع البيانات الوصف1idINTمعرّف الحقل، مفتاح رئيس2post_idINTمفتاح خارجي إلى معرّف المنشور3tag_idINTمفتاح خارجي إلى معرّف الوسمجدول المنشوراتالتسلسل الحقل نوع البيانات الوصف1idINTمعرّف المنشور، مفتاح رئيس2urlVarchar(255)رابط المنشور3titleVarchar(140)عنوان المنشور4descriptionVarchar(170)وصف المنشور5contentTextمحتوى المنشور6blogTinyint(1)يحدد طبيعة المنشور7category_idINTمعرّف تصنيف المنشور، مفتاح خارجي8imageVarchar(255)رابط صورة المنشورملف التهجير الخاص بمنشورات المدونةأنشأنا في درس تهجير قواعد البيانات فيLaravel 5 ملف التهجير الخاص بالمنشورات إلا أننا لم نضف معرف التصنيف category_id ولا صورة المنشور image؛ سننشئ في هذا الدرس ملف تهجير لإضافة هذين الحقلين. نفذ الأمر التالي في مجلد التطبيق: php artisan make:migration add_category_id_image_to_posts --table=postsافتح ملف التهجير المنشأ بالأمر السابق وعدله ليصبح كالتالي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AddCategoryIdImageToPosts extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('posts', function (Blueprint $table) { $table->string('image')->nullable()->after('content'); $table->unsignedInteger('category_id')->nullable()->after('blog'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('posts', function (Blueprint $table) { $table->dropColumn('image'); $table->dropColumn('category_id'); }); } } نضيف حقلا جديدا لصورة المنشور، يُضاف الحقل بعد حقل المحتوى content ويمكن أن يكون فارغا: $table->string('image')->nullable()->after('content');نضيف أيضا حقلا لمعرِّف التصنيف بعد حقل blog $table->unsignedInteger('category_id')->nullable()->after('blog');نفذ الأمر التالي لشغيل ملف التهجير وإضافة الحقول: php artisan migrateملف التهجير الخاص بتصنيفات المدونةننتقل الآن لملف التهجير الذي سيتولى إنشاء جدول تصنيفات المنشورات. سنستخدم هذا الملف أيضا لإدراج تسجيلات في الجدول، كل تسجيلة تمثل تصنيفا: php artisan make:migration blog_categoriesعدل ملف التهجير كالتالي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class BlogCategories extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('blog_categories', function (Blueprint $table) { $table->increments('id'); $table->string('category')->unique(); $table->timestamps(); }); DB::table('blog_categories')->insert([ 'category' => "WOMEN" ]); DB::table('blog_categories')->insert([ 'category' => "MEN" ]); DB::table('blog_categories')->insert([ 'category' => "KIDS" ]); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('blog_categories'); } } ملف التهجير الخاص بالوسومالخطوة التالية هي إنشاء تهجير لوسوم المدونة: php artisan make:migration blog_tagsعدل ملف التهجير كالتالي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class BlogTags extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('blog_tags', function (Blueprint $table) { $table->increments('id'); $table->string('tag')->unique(); $table->timestamps(); }); DB::table('blog_tags')->insert([ 'tag' => "Pink" ]); DB::table('blog_tags')->insert([ 'tag' => "T-Shirt" ]); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('blog_tags'); } }ملف التهجير الخاص بربط المنشورات والوسومآخر ملف من ملفات التهجير هو الملف الخاص بجدول الوسوم-المنشورات. ننشئه بالأمر التالي: php artisan make:migration blog_post_tagsعدّل الملف على النحو التالي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class BlogPostTags extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('blog_post_tags', function (Blueprint $table) { $table->increments('id'); $table->unsignedInteger('post_id'); $table->unsignedInteger('tag_id'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('blog_post_tags'); } }أنشأنا ملفات التهجير، ننفذ أمر migrate لتطبيق التهجيرات: php artisan migrateملحوظة: يجب دائما البدء بتهجيرات الجداول التي لا تحتاج لجداول أخرى، بمعنى أنه لا توجد بها مفاتيح خارجية Foreign keys. لتهجير جدول به مفتاح خارجي لجدول آخر يجب أن يكون هذا الجدول الأخير قد تم إنشاؤه. بذر جدول منشورات المدونةسنستخدم مكتبة Faker لإضافة منشورات وهمية نختبر بها مدونتنا. نفذ الأمر التالي لإنشاء ملف بذر لمنشورات المدونة: php artisan make:seeder BlogPostsTableSeederافتح الملف database/seeds/BlogPostsTableSeeder.php وعدله ليصبح كما يلي: <?php use Illuminate\Database\Seeder; class BlogPostsTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { $faker = Faker\Factory::create(); for ($i = 0; $i < 10; $i++){ DB::table('posts')->insert([ //, 'url' => $faker->unique()->word, 'title' => $faker->unique()->sentence($nbWords = 6), 'description' => $faker->paragraph($nbSentences = 3), 'content' => $faker->text, 'image' => $faker->randomElement($array = array ('blog-one.jpg','blog-two.jpg','blog-three.jpg')), 'blog' => '1', 'category_id' => $faker->numberBetween($min = 1, $max = 3), ]); } } }نولد كلمة عشوائية فريدة لاستخدامها عنوانا للمنشور: 'url' => $faker->unique()->wordنختار صورة عشوائية من بين ثلاث صور لاستخدامها صورة للمنشور: 'image' => $faker->randomElement($array = array ('blog-one.jpg','blog-two.jpg','blog-three.jpg'))أنشأنا في تهجير تصنيفات المدونة ثلاثة تصنيفات، لذا سيقتصر اختيار معرفات التصنيفات على المجال [1,3]: 'category_id' => $faker->numberBetween($min = 1, $max = 3),سنستخدم الحقل created_at لعرض تاريخ المنشور في المدونة: 'created_at' => $faker->dateTime($max = 'now'),نفذ أمر artisan التالي لتطبيق البذر: php artisan db:seed --class=BlogPostsTableSeederبذر جدول الوسوم-المنشوراتننتقل الآن لبذر الجدول blog_post_tags الذي يُستخدَم لربط المنشورات بالوسوم. php artisan make:seeder BlogPostTagsTableSeederافتح ملف البذر وعدله كالتالي: <?php use Illuminate\Database\Seeder; class BlogPostTagsTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { $faker = Faker\Factory::create(); for ($i = 1; $i < 11; $i++){ DB::table('blog_post_tags')->insert([ //, 'post_id' => $i, 'tag_id' => $faker->numberBetween($min = 1, $max = 2), ]); } } }أدرجنا عند بذر جدول الوسوم BlogPostsTableSeeder.php عشر تسجيلات فقط، لذا حرصنا ألا تتعدى قيمة معرف المنشور post_id في جدول الوسوم-المنشورات هذا الحد: for ($i = 1; $i < 11; $i++)بالنسبة لمعرّف الوسوم فقد حددنا المجال بـ[1,2] لأننا أثناء تهجير الوسوم أضفنا وسمين في جدول قاعدة البيانات. نفذ الأمر التالي لتطبيق بذر جدول الوسوم-المنشورات: php artisan db:seed --class=BlogPostTagsTableSeederنماذج المدونةننتقل بعد تنفيذ التهجيرات إلى إنشاء نماذج المدونة. سننشئ النماذج التالية: نموذج المنشور Post وسيكون مسؤولا عن التفاعل مع جدول المنشورات posts.نموذج تصنيف المدونة BlogCategory وهو مسؤول عن التفاعل مع جدول تصنيفات المدونة blog_categories.نموذج وسم المدونة BlogTag ويُعنى بالتخاطب مع جدول وسوم المدونة blog_tags.نموذج وسم منشورات المدونة BlogPostTag ويتفاعل مع جدول وسوم منشورات المدونة blog_post_tags.نفذ الأوامر التالية لإنشاء النماذج: php artisan make:model Post php artisan make:model BlogCategory php artisan make:model BlogTag php artisan make:model BlogPostTagلم نضف أمر إنشاء نموذج لمنشور المدونة لأننا أنشأناه خلال درس Eloquent من هذه السلسة. نبدأ بالتعديل على النماذج. نموذج منشور المدونةسنضيف إلى مدونتنا إمكانية الانتقال إلى المنشور السابق أو التالي؛ نستخدم معرّف المنشور لتحديد المنشور السابق و التالي. ننشئ دالتين لهذا الغرض: prevBlogPostURL (المنشور السابق) وnextBlogPostURL (المنشور التالي). <?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { protected $primaryKey = 'id'; protected $table = 'posts'; protected $fillable = array('url', 'title', 'description','content','blog','created_at_ip', 'updated_at_ip'); public static function prevBlogPostUrl($id) { $blog = static::where('id', '<', $id)->orderBy('id', 'desc')->first(); return $blog ? $blog->url : '#'; } public static function nextBlogPostUrl($id) { $blog = static::where('id', '>', $id)->orderBy('id', 'asc')->first(); return $blog ? $blog->url : '#'; } public function tags() { return $this->belongsToMany('App\BlogTag','blog_post_tags','post_id','tag_id'); } }استخدمنا دالتي where وfirst، وهما دالّتان توفرهما نماذج Eloquent، للحصول على معرّفيْ المنشورين السابق والتالي. بالنسبة لـwhere في دالة prevBlogPostUrl استخدمنا عامل المقارنة > (أصغر من) للحصول على المنشورات ذات المعرف الأصغر من معرف المنشور الحالي ثم رتبناها تنازليا (معطى desc في orderBy) وأخذنا العنصر الأول first. $blog = static::where('id', '<', $id)->orderBy('id', 'desc')->first();نفس المبدأ في دالة nextBlogPostUrl مع استخدام عامل المقارنة أكبر من < والترتيب التصاعدي asc. إن أردنا ترجمة التعليمة باستعلامات SQL فسنحصُل على التالي (مثال مع منشور ذي معرّف 3): SELECT * FROM posts where id < 3 ORDER BY id LIMIT 1;العلاقة بين الوسوم والمنشورات هي من النوع متعدّد إلى متعدّد Many to many: يمكن أن يوجد أكثر من وسم على المنشور، كما يمكن لوسم أن يوجد على أكثر من منشور. تُنفّذ هذه العلاقة بإدخال جدول وسيط للربط بين الجدولين posts وblog_tags. استخدمنا دالة belongsToMany في Eloquent لتعريف علاقة من هذا النوع: $this->belongsToMany('App\BlogTag','blog_post_tags','post_id','tag_id');تأخذ الدالة أربعة معطيات. الأول اسم النموذج الذي يرتبط بالنموذج الحالي بهذه العلاقة (BlogTag)، الثاني اسم الجدول الوسيط (blog_post_tags)، الثالث المفتاح الخارجي في الجدول المصدر (جدول المنشورات إذا كنا في نموذج المنشور) والرابع المفتاح الخارجي للجدول الوجهة (أي جدول الوسوم). تعريف الدالة ()tags واستخدام belongsToMany داخلها بالطريقة السالفة الذكر يجعل الحصول على وسوم منشور بسهولة كتابة: $tags = $post->tags استخدام هذه الدالة يكافئ تنفيذ استعلام SQL التالي: SELECT `blog_tags`.*, `blog_post_tags`.`post_id` AS `pivot_post_id`, `blog_post_tags`.`tag_id` AS `pivot_tag_id` FROM `blog_tags` INNER JOIN `blog_post_tags` ON `blog_tags`.`id` = `blog_post_tags`.`tag_id` WHERE `blog_post_tags`.`post_id` = ? ; قد يقنعك النظر في الاستعلام أعلاه بجدوى استخدام نماذج Eloquent. نموذج تصنيف المدونةنموذج التصنيفات سهل ولا يحتاج لأي شيء خاص: <?php namespace App; use Illuminate\Database\Eloquent\Model; class BlogCategory extends Model { protected $fillable = array('category'); }نموذج وسم المدونةتنطبق على نموذج الوسم علاقة متعدّد إلى متعدّد التي تنطبق على نموذج المنشور، لذا سنضيف دالة posts إلى النموذج لتعريف العلاقة بين جدولي الوسوم والمنشورات. <?php namespace App; use Illuminate\Database\Eloquent\Model; class BlogTag extends Model { protected $fillable = array('tag'); public function posts() { return $this->belongsToMany('App\Post','blog_post_tags','post_id','tag_id'); } }لاحظ استخدام belongsToMany بنفس طريقة استخدامها في نموذج المنشور. نموذج وسم منشورات المدونةيمثل هذا النموذج الجدول الوسيط blog_post_tags. <?php namespace App; class BlogPostTag extends Model { protected $fillable = array('post_id', 'tag_id'); }دوال المتحكم الخاصة بالمدونةتوجد في المتحكم Front دالتان تختصان بالمدونة: blog وblog_post. أضف السطر التالي لاستيراد نوذج المنشور Post إلى المتحكم: use App\Post;دالة Blogتُستخدَم هذه الدالة لعرض صفحة المدونة وإظهار جميع منشوراته. إذا كان عدد المنشورات كبيرا فسيكون من العبث عرضُها دفعةَ واحدة، لذا سنستخدم التّصفيح Pagination (عرض عدد محدود من المنشورات في كل صفحة). يدعم Eloquent إعداد الصفحات: public function blog() { $posts = Post::where('id', '>', 0)->paginate(3); $posts->setPath('blog'); $data['posts'] = $posts; return view('blog', array('data' => $data, 'title' => 'Latest Blog Posts', 'description' => '', 'page' => 'blog', 'brands' => $this->brands, 'categories' => $this->categories, 'products' => $this->products)); }نبحث عن منشورات المدونة ثم نُعِدّ صفحاتها، نحدّد عدد المنشورات في كل صفحة بثلاثة منشورات: $posts = Post::where('id', '>', 0)->paginate(3);نحدّد الرابط الخاص بإعداد الصفحات، اخترنا الرابط http://larashop.dev/blog: $posts->setPath('blog');ثم نحتفظ بالنتائج في المصفوفة data التي سنمررها إلى العرض. دالة Blog_postتتلقى هذه الدالة رابطا ثم تعثر على منشور اعتمادا على الرابط الممرّر إليها: public function blog_post($url) { $post = Post::where('url', '=' , $url)->first(); $previous_url = Post::prevBlogPostUrl($post->id); $next_url = Post::nextBlogPostUrl($post->id); $data['tags'] = $post->tags; $data['title'] = $post->title; $data['description'] = $post->description; $data['content'] = $post->content; $data['blog'] = $post->blog; $data['created_at'] = $post->created_at; $data['image'] = $post->image; $data['previous_url'] = $previous_url; $data['next_url'] = $next_url; return view('blog_post', array('data' => $data, 'page' => 'blog'));لاحظ استخدام الدالة tags التي عرفناها في النموذج Post. عروض المدونةتوجد عروض المدونة في الملف المرفق. يتعلق الأمر بالعرضين blog.blade.php و blog_post.blade.php الذي عُدّل عليهما لعرض البيانات الممرّرة. لا توجد تعليمات جديدة علينا في العرضين سوى التعليمة {!! $data['posts']->render() !!}تعمل هذه التعليمة على ترقيم الصفحات لتسهيل تصفح منشورات المدونة. تذكر أننا في الدالة blog كتبنا التعليمة التالية $posts = Post::where('id', '>', 0)->paginate(3);لإعداد الصفحات بحيث تُنشَر كل ثلاثة منشورات دفعة واحدة مع إتاحة التنقل إلى بقية المنشورات. تنشئ الدالة render في قالب Blade روابط من شكل http://laravel.dev/blog?page=X حيث X رقم الصفحة. بما أننا بذرنا عشرة منشورات فسيكون لدينا أربع صفحات (3 منشورات في كل من الصفحات 1 إلى 3، ومنشور واحد في الصفحة الرابعة، الأخيرة). الملف المرفق: عروض المدونة. ترجمة -وبتصرّف- لمقال Laravel 5 Blog Tutorial لصاحبه Rodrick Kazembe.
    1 نقطة
  6. يهدف هذا الدرس إلى بناء تطبيق CRUD (إدراج بيانات في قاعدة بيانات، القراءة منها، تحديثها وحذفها؛ اختصار لـUpdate، Read، Create وDelete). التطبيق عبارة عن واجهة لإدارة لائحة من الموظفين: إضافة موظّف، تحرير بياناته أو حذفها. سنستخدم Laravel 5 للنهاية الخلفية Backend و AngularJS للنهاية الأمامية Frontend. سنستخدم أيضا Bootstrap لإضافة لمسة جمالية إلى التطبيق. هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي: مدخل إلى Laravel 5.تثبيت Laravel وإعداده على كلّ من Windows وUbuntu.أساسيات بناء تطبيق باستخدام Laravel.إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel.نظام Blade للقوالب.تهجير قواعد البيانات في Laravel.استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها.إنشاء سلة مشتريات في Laravel.الاستيثاق في Laravel.إنشاء واجهة لبرمجة التطبيقات API في Laravel.إنشاء مدوّنة باستخدام Laravel.استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel. (هذا الدرس)الدوّال المساعدة المخصّصة في Laravel.استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار. AngularJS هو إطار عمل جافاسكريبت قويّ وفعّال، يتبنى مبدأ النموذج-العرض-المتحكم MVC ويعمل لدى العميل (المتصفّح). للاطلاع على المزيد عن AngularJS تابع سلسلة دروس مدخل إلى تعلم AngularJS . يفترض هذا الدرس معرفة أساسيات Laravel 5، تثبيت كلّ من PHP، MySQL، ِApache وComposer. يغطي الدرس المواضيع التالية: إنشاء نهاية خلفية في Laravel 5، ستكون عبارة عن واجهة برمجية API.بنية تطبيق AngularJS.واجهة برمجية باستخدام Laravel 5ننشئ في هذه الفقرة النهاية الخلفية للتطبيق الذي نعمل عليه. سيتولى Laravel هذه المهمة. نبدأ بإنشاء تطبيق Laravel ثم نعدّه لتوفير الواجهة البرمجية. الخطوة الأولى: إنشاء تطبيق Laravelننفذ الأمر التالي في أصل المستند Document root لإنشاء مشروع Laravel باسم angulara: composer create-project laravel/laravel angularaراجع درس تثبيت Laravel 5 وإعداده على Windows وUbuntu للمزيد حول تثبيت Laravel وإعداده. سنفترض في بقية هذا الدرس تثبيت Laravel على المنصة المفضلة لديك وإنشاء مضيف افتراضي باسم angulara.dev. الخطوة التالية هي إعداد تهجير قاعدة البيانات. الخطوة الثانية: إعداد قاعدة البياناتستحتاج لقاعدة بيانات للعمل مع التطبيق. استخدم برنامج إدارة قاعدة البيانات المفضل لديك أو نفذ الأمر التالي في سطر أوامر MySQL لإنشاء قاعدة بيانات للمشروع: CREATE DATABASE `angulara`;ننتقل الآن لإعداد Laravel لكي يعمل مع قاعدة البيانات. افتح ملف env. في مجلد تطبيق Laravel وعدل القيم التالية بما يناسب: DB_HOST=localhost // اسم قاعدة البيانات DB_DATABASE=angulara // اسم مستخدم في MySQL لديه صلاحيات الكتابة والقراءة في القاعدة أعلاه DB_USERNAME=root // كلمة سر المستخدم DB_PASSWORD=melodyاحفظ التعديلات. نستغل أداة Artisan لإنشاء ملف تهجير خاص بجدول يحوي بيانات الموظفين employees. نفذ الأمر التالي لإنشاء ملف التهجير: php artisan make:migration create_employees_tableستحصُل على الرسالة التالية التي تعرض اسم الملف المنشأ: Created Migration: 2016_01_05_203637_create_employees_tableينشئ الأمر ملفا في المجلد database/migrations، نفتحه للتعديل عليه. عدّل المحتوى كالتالي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateEmployeesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('employees', function (Blueprint $table) { $table->increments('id'); $table->string('name')->unique(); $table->string('email')->unique(); $table->string('contact_number'); $table->string('position'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('employees'); } }احفظ التعديلات ثم نفذ أمر ِArtisan التالي: php artisan migrateينفذ الأمر التهجيرات وينشئ جدول بيانات الموظفين. تظهر الرسائل التالية بعد تنفيذ الأمر: Migration table created successfully. Migrated: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_100000_create_password_resets_table Migrated: 2016_01_05_203637_create_employees_tableتحقق من قاعدة بيانات MySQL، ستجد أن جدولا جديدا أُدرِج في القاعدة. الخطوة الثالثة: إنشاء واجهة برمجيةننشئ متحكما Controller للتطبيق، سنسميه Employees: php artisan make:controller Employeesثم يأتي دور النموذج Model: php artisan make:model Employeeسنضيف مصفوفة في النموذج لتفعيل الإسناد الشامل؛ افتح ملف النموذج وعدّله على النحو التالي: <?php namespace App; use Illuminate\Database\Eloquent\Model; class Employee extends Model { protected $fillable = array('id', 'name', 'email','contact_number','position'); }احفظ التعديلات. ننتقل للتعديل على المتحكم. افتح ملف المتحكم Employees وعدله ليصبح كالتالي <?php namespace App\Http\Controllers; use App\Employee; use Illuminate\Http\Request; use App\Http\Requests; use App\Http\Controllers\Controller; class Employees extends Controller { /** * Display a listing of the resource. * * @return Response */ public function index($id = null) { if ($id == null) { return Employee::orderBy('id', 'asc')->get(); } else { return $this->show($id); } } /** * Store a newly created resource in storage. * * @param Request $request * @return Response */ public function store(Request $request) { $employee = new Employee; $employee->name = $request->input('name'); $employee->email = $request->input('email'); $employee->contact_number = $request->input('contact_number'); $employee->position = $request->input('position'); $employee->save(); return 'Employee record successfully created with id ' . $employee->id; } /** * Display the specified resource. * * @param int $id * @return Response */ public function show($id) { return Employee::find($id); } /** * Update the specified resource in storage. * * @param Request $request * @param int $id * @return Response */ public function update(Request $request, $id) { $employee = Employee::find($id); $employee->name = $request->input('name'); $employee->email = $request->input('email'); $employee->contact_number = $request->input('contact_number'); $employee->position = $request->input('position'); $employee->save(); return "Sucess updating user #" . $employee->id; } /** * Remove the specified resource from storage. * * @param int $id * @return Response */ public function destroy($id = null) { if ($id == null) { } else { $employee = Employee::find($id); $employee->delete(); return "Employee record successfully deleted #" . $id; } } }يعرِّف المتحكم الدوالّ index لسرد قائمة بالموظفين، store لإضافة موظف جديد، show لعرض موظف بناء على معرّفه، update لتحديث بيانات موظّف وdestroy لحذف موظّف. تبقى لنا إعداد المسارات Routes في Laravel. افتح ملف المسارات routes.php وعدله كالتالي: <?php /* |-------------------------------------------------------------------------- | Application Routes |-------------------------------------------------------------------------- | | Here is where you can register all of the routes for an application. | It's a breeze. Simply tell Laravel the URIs it should respond to | and give it the controller to call when that URI is requested. | */ Route::get('/', function () { return view('index'); }); Route::get('/api/v1/employees/{id?}', 'Employees@index'); Route::post('/api/v1/employees', 'Employees@store'); Route::post('/api/v1/employees/{id}', 'Employees@update'); Route::delete('/api/v1/employees/{id}', 'Employees@destroy');لاحظ استخدام إجراءات HTTP وفقا للمبدأ المشروح في درس إنشاء واجهة برمجية API في Laravel 5. يختلف التعامل مع المسار api/v1/employees حسب إجراء HTTP المستخدم: get يُستخدم للحصول على معلومات موظف أو قائمة بالموظفين، post لإضافة موظف جديد، put لتحديث بيانات موظّف وdelete لحذف موظّف. أكملنا الآن جانب النهاية الخلفية بإنشاء واجهة برمجية. ننتقل للواجهة الأمامية التي ستستخدم الواجهة البرمجية للحصول على بيانات الموظفين وتنسيقها قبل عرضها في المتصفح. بنية تطبيق AngularJSسيأخذ مجلد public (الواجهة الأمامية لتطبيق Laravel) الشكل التالي: يحوي المجلّد الفرعي app ملفات جافاسكريبت التابعة لـAngularJS.توجد متحكمات AngularJS في المجلّد app/controllers.توجد ملفات نواة AngularJS في المجلّد app/lib. توجد أيضا إمكانية استخدام شبكة توصيل محتوى Content delivery network, CDN.توجد ملفات CSS في المجلد css.ملفات جافاسكريبت غير التابعة لـAngularJS توجد في المجلد js.توجد ملفات الواجهة الأمامية في الملف المرفق، سنشرح ما يحتاج لشرح منها. الملف app.jsسنستخدم الملف public/app/app.js لتعريف التطبيق الخاص بنا: var app = angular.module('employeeRecords', []) .constant('API_URL', 'http://angulara.dev/api/v1/');ننشئ وحدة Module في AngularJS ونسند الكائن إلى المتغير app. سيُستخدم هذا المتغير في جميع ملفات AngularJS؛ ثم نعرّف ثابتا Constant لرابط الواجهة البرمجية API_URL. ملحوظة: إن كنت اخترت اسما مختلفا للمضيف فضعه مكان angulara.dev. المتحكم Employees.jsسيكون هذا الملف مسؤولا عن التفاعل مع عروض تطبيق AngularJS: app.controller('employeesController', function($scope, $http, API_URL) { // الحصول على لائحة الموظفين $http.get(API_URL + "employees") .success(function(response) { $scope.employees = response; }); // عرض نافذة منبثقة $scope.toggle = function(modalstate, id) { $scope.modalstate = modalstate; switch (modalstate) { case 'add': $scope.form_title = "Add New Employee"; break; case 'edit': $scope.form_title = "Employee Detail"; $scope.id = id; $http.get(API_URL + 'employees/' + id) .success(function(response) { console.log(response); $scope.employee = response; }); break; default: break; } console.log(id); $('#myModal').modal('show'); } //save new record / update existing record $scope.save = function(modalstate, id) { var url = API_URL + "employees"; var request_method = 'POST'; //append employee id to the URL if the form is in edit mode if (modalstate === 'edit'){ url += "/" + id; request_method = 'PUT'; } $http({ method: request_method, url: url, data: $.param($scope.employee), headers: {'Content-Type': 'application/x-www-form-urlencoded'} }).success(function(response) { console.log(response); location.reload(); }).error(function(response) { console.log(response); alert('This is embarassing. An error has occured. Please check the log for details'); }); } //delete record $scope.confirmDelete = function(id) { var isConfirmDelete = confirm('Are you sure you want this record?'); if (isConfirmDelete) { $http({ method: 'DELETE', url: API_URL + 'employees/' + id }). success(function(data) { console.log(data); location.reload(); }). error(function(data) { console.log(data); alert('Unable to delete'); }); } else { return false; } } });نعرِّف متحكما باسم employeesController في المتغيّر app الذي أنشأناه في الملف app.js. حدّدنا الاعتماديات بـ $http، scope$ وAPI_URL. نستدعي خدمة http$ في AngularJS لإرسال طلب إلى الواجهة البرمجية، مع تمرير المعطى API_URL + "employees": $http.get(API_URL + "employees").success(function(response) {$scope.employees = response;});عند نجاح الطلب نُسنِد الإجابة إلى المتغير scope.employees$ الذي سيصبح متاحا في العرض View لإظهار محتواه. تعرض الدالة: $scope.toggle = function(modalstate, id) {…}نافذة منبثقة تحوي استمارة لإضافة موظّف جديد أو تعديل بيانات موظّف موجود حسب الحالة. نستخدم الدالة: $scope.save = function(modalstate, id){…}في حالتيْ الإضافة والتعديل. بالنسبة لإضافة موظّف نستخدم إجراء POST؛ وفي حالة التعديل نستخدم الإجراء PUT. تحذف الدالة: $scope.confirmDelete = function(id){…}بيانات موظّف من جدول الموظفين. عرض البيانات المتحصل عليها من الواجهة البرمجية بـAngularJSسننشئ عرضا لإظهار البيانات التي نتحصل عليها من الواجهة البرمجية؛ يستخدم كل من angularJS وBlade الحاضنات المزدوجة {{}} لعرض البيانات، لذا لن نحفظ عرض AngularJS بلاحقة blade.php حتى لا يعدّ نظام Blade العرض موجها له. محتوى العرض هو التالي، نحفظ الملف index.php في ملف العروض resources/views حتى يُحمّل عند طلبه من المسار / (الصفحة الرئيسية للموقع): <!DOCTYPE html> <html lang="en-US" ng-app="employeeRecords"> <head> <title>Laravel 5 AngularJS CRUD Example</title> <!-- Load Bootstrap CSS --> <link href="<?= asset('css/bootstrap.min.css') ?>" rel="stylesheet"> </head> <body> <h2>Employees Database</h2> <div ng-controller="employeesController"> <!-- Table-to-load-the-data Part --> <table class="table"> <thead> <tr> <th>ID</th> <th>Name</th> <th>Email</th> <th>Contact No</th> <th>Position</th> <th><button id="btn-add" class="btn btn-primary btn-xs" ng-click="toggle('add', 0)">Add New Employee</button></th> </tr> </thead> <tbody> <tr ng-repeat="employee in employees"> <td>{{ employee.id }}</td> <td>{{ employee.name }}</td> <td>{{ employee.email }}</td> <td>{{ employee.contact_number }}</td> <td>{{ employee.position }}</td> <td> <button class="btn btn-default btn-xs btn-detail" ng-click="toggle('edit', employee.id)">Edit</button> <button class="btn btn-danger btn-xs btn-delete" ng-click="confirmDelete(employee.id)">Delete</button> </td> </tr> </tbody> </table> <!-- End of Table-to-load-the-data Part --> <!-- Modal (Pop up when detail button clicked) --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="myModalLabel">{{form_title}}</h4> </div> <div class="modal-body"> <form name="frmEmployees" class="form-horizontal" novalidate=""> <div class="form-group error"> <label for="inputEmail3" class="col-sm-3 control-label">Name</label> <div class="col-sm-9"> <input type="text" class="form-control has-error" id="name" name="name" placeholder="Fullname" value="{{name}}" ng-model="employee.name" ng-required="true"> <span class="help-inline" ng-show="frmEmployees.name.$invalid && frmEmployees.name.$touched">Name field is required</span> </div> </div> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">Email</label> <div class="col-sm-9"> <input type="email" class="form-control" id="email" name="email" placeholder="Email Address" value="{{email}}" ng-model="employee.email" ng-required="true"> <span class="help-inline" ng-show="frmEmployees.email.$invalid && frmEmployees.email.$touched">Valid Email field is required</span> </div> </div> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">Contact Number</label> <div class="col-sm-9"> <input type="text" class="form-control" id="contact_number" name="contact_number" placeholder="Contact Number" value="{{contact_number}}" ng-model="employee.contact_number" ng-required="true"> <span class="help-inline" ng-show="frmEmployees.contact_number.$invalid && frmEmployees.contact_number.$touched">Contact number field is required</span> </div> </div> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">Position</label> <div class="col-sm-9"> <input type="text" class="form-control" id="position" name="position" placeholder="Position" value="{{position}}" ng-model="employee.position" ng-required="true"> <span class="help-inline" ng-show="frmEmployees.position.$invalid && frmEmployees.position.$touched">Position field is required</span> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" id="btn-save" ng-click="save(modalstate, id)" ng-disabled="frmEmployees.$invalid">Save changes</button> </div> </div> </div> </div> </div> <!-- Load Javascript Libraries (AngularJS, JQuery, Bootstrap) --> <script src="<?= asset('app/lib/angular/angular.min.js') ?>"></script> <script src="<?= asset('js/jquery.min.js') ?>"></script> <script src="<?= asset('js/bootstrap.min.js') ?>"></script> <!-- AngularJS Application Scripts --> <script src="<?= asset('app/app.js') ?>"></script> <script src="<?= asset('app/controllers/employees.js') ?>"></script> </body> </html>نربط تطبيق AngularJS بوسم html حتى يكون له كامل التحكّم في العناصر الموجودة في الصفحة: <html lang="en-US" ng-app="employeeRecords"> نفس الشيء بالنسبة للمتحكم employeesController الذي نربطه بعنصر div حتى نجعل جميع دوال المتحكم متاحة في هذا العنصر: <div ng-controller="employeesController">نستخدم تعليمة ng-repeat للمرو على جميع عناصر المجموعة employees: <tr ng-repeat="employee in employees">تعمل ng-repeat بطريقة مشابهة لعمل الحلقة التكرارية foreach. التحقق من بيانات استمارات AngularJSاستخدمنا في استمارات الموظفين طرقا للتحقق من المُدخلات. اعثر على الشفرات التالية في ملف العرض index.php ولاحظ استخدامها: <form name="frmEmployees" class="form-horizontal" novalidate="">تعرّف هذه الشفرة استمارة باسم frmEmployees وتضيف إليها خاصيّة novalidate للطلب من HTML 5 الامتناع عن تدقيق الاستمارة، سنتولى الأمر. <input type… ng-model="employee.name" ng-required="true">تستخدم تعليمة ng-model لربط حقول الاستمارة ببيانات النموذج Employee. ربطنا الحقل أعلاه بخاصية name في النموذج. بهذه الطريقة يكون محتوى الحقل متاحا للنموذج، والعكس أيضا. تدل التعليمة ng-required أن الحقل مطلوب. إن لم تذكر قيمة لهذا الحقل فلن يمكن إرسال الاستمارة. <span class="help-inline" ng-show="frmEmployees.name.$invalid && frmEmployees.name.$touched">لا يظهر هذا العنصُر إلا إذا أخفق التحقق من حقل name قبله. تظهر رسالة تفيد أن قيمة الحقل مطلوبة. ng-disabled="frmEmployees.$invalid" تعطّل هذه التعليمة إمكانية إرسال الاستمارة عند إخفاق التحقق من أحد الحقول المطلوبة. حان الآن وقت تجربة ما عملناه في الخطوات السابقة، افتح الموقع (بالنسبة لي اخترتُ إنشاء مضيف افتراضي angulara.dev): http://angulara.dev/ستحصُل، إن اتبعت الخطوات السابقة، على الواجهة التالية: اضغط على زر Add New Employee لإضافة موظّف. ستظهر نافذة منبثقة لإضافة بيانات الموظّف. تصبح الواجهة بعد إضافة موظفين على النحو التالي: تمكّن الأزرار edit و delete الموجودة في كل سطر تحديثَ أو حذف بيانات موظّف. الملف المرفق: مجلد public. ترجمة -وبتصرّف- لمقال Laravel 5 AngularJS Tutorial لصاحبه Rodrick Kazembe.
    1 نقطة
  7. سأجتاز امتحان لنيل شهادة +Security بعد حوالي 15 يوماً ابتداً من اليوم، فهل هذه المدة تعتبر كافيةً للإعداد الجيد لها؟ وهل من نصائح للتركيز على الإعداد؟ مع العلم أنّ لي بعض المعارف في CISSP.
    1 نقطة
  8. نعم صعبة بعض الشيء، لكن بالمقابل لا تدع هذا الأمر يحُطّ من عزيمتك ويُحبطك، ذلك لأنه أمر عادي وإلا لكانت الشهادات سهلة وتعطى لأيٍ كان -دون وجود فارق الكفاءة-، وكنصيحة أنصحك بـ كتاب Don Poulton الذي يعتبر مرجعا مهما في هذا التخصص، بالإضافة إلى ذلك ابحث عن أمثلة لامتحانات سابقة وحاول الإجابة عنها، هذا الأمر سيمنحك امتيازين مهمين، الأول أنك ستعتاد على نوعية الأسئلة المطروحة وتكتشف جل الحيثيات وطرق طرحها، الامتياز الثاني أنك ستكتشف مكامن النقص لديك وتحاول تداركها عن طريق دروس ومقالات متخصصة في ذلك. تذكر أن الاستعداد الجيد للامتحان وحده الكفيل بجعله سهلا وفي المتناول، وتبقى درجة الصعوبة مختلفة من ممتحن لآخر تتناسب اطرادا وَ درجة استعداده.
    1 نقطة
  9. لا أحد يحدد لك ذلك، في النهاية من سيراقب مالذي تفعلينه من خلال شاشة جهازك. أعرف عدد من الأصدقاء ممن يعملون وهم في أشهرهم الأولى من اللجوء، لكن في هذه المرحلة لن يمكنك استلام المبلغ، راكميه ثم ابحثي عن من تثقين به ويمكنه استلام المبلغ عنك وتسليمه لك في اليد كل التوفيق
    1 نقطة
  10. الأخ طريف لقد راسلت الإدارة بخصوص تقديم دورة مهمة في أنظمة لينكس و التي ستخول للمستفيد منها أن يجتاز امتحانات نيل شواهد لينكس بسهولة لكن لم تراسلني الإدارة ما إذا كان الموضوع نال إعجابهم أم لا !
    1 نقطة
  11. أخي الكريم شهادة cisco هي المتعلقة بالشبكات و تلزمك دراية مهمة و شاملة بخصوص الشبكات أما شهادة RedHat متخصة بتوزيعة لينكس RedHat و أعتقد أنه لشهادة cisco يلزمك دراستها في أحد المعاهد لأن دراستها طويلة
    1 نقطة
  12. أخي سؤالك غير مفهوم ف ال iptables تستخدم لمنع أو تمكين الإتصال بعنوان ip أو عده عناوين ip و ليس للربط بين الشبكات!
    1 نقطة
  13. نعم يمكنك إزالته و استبداله ب : أطلبه من الموقع : https://disqus.com/profile/login/
    1 نقطة
  14. هل توجد طريقة لتوليد الحروف العشوائية في بايثون؟ لا تهمني حالة الأحرف لو كانت كبيرة أو صغيرة، المهم هو حرف واحد عشوائي كل مرة.
    1 نقطة
  15. يوجد عدة طرق في لغة بايثون لفعل ذلك، وأسهلها هو استخدام مكتبة PyEnchant، والتي تأتي بعدّة قواميس وبلغات مختلفة مثل (en_GB, en_US, de_DE, fr_FR) حيث يجب عليك في البداية أن تختار القاموس المناسب ومن ثم يمكنك التأكد من وجوده في القاموس أو لا عن طريق دالة check() أو يمكنك الحصول على مقترحات للكلمة عن طريق دالة suggest() كما في الأمثلة التالية: >>> import enchant >>> d = enchant.Dict("en_US") >>> d.check("Hello") True >>> d.check("Helo") False >>> d.suggest("Helo") ['He lo', 'He-lo', 'Hello', 'Helot', 'Help', 'Halo', 'Hell', 'Held', 'Helm', 'Hero', "He'll"] >>>
    1 نقطة
  16. بايثون (Python) لغة ممتازة لبرمجة الويب نظرا لمرونتها وأدائها العالي. أطُرُ الويب يمكن أن تجعل برمجة تطبيقات الويب أبسط بكثير لأنها توصل العديد من المكونات الضرورية مع بعضها للحصول على تطبيق قوي. في حين تهدف بعض أطر الويب إلى توفير كل شيء يمكن أن يرغب به المستخدم لتطوير تطبيق ما، هناك أطر أخرى تحاول البقاء بعيدا والاهتمام بالأهم، Bottle إطار للغة بايثون يندرج ضمن النوع الثاني. إنه بالفعل خفيف ومصغر، لكنه يجعل تطوير التطبيقات سهلا وسريعا. في هذا المقال، سنعرض طريقة ضبط واستعمال إطار العمل المصغّر Bottle لإنشاء تطبيقات ويب بسيطة وباستعمال لغة Python. كيفية تثبيت Bottleتثبيت Pythonإطار Bottle مبني على لغة Python وهي مثبتة مسبقا على أنظمة لينكس وOS X، أما بالنسبة لنظام Windows فيمكن تنصيب Python 2 عبر تحميلها من موقعها الرسمي. الجدير بالذّكر أن هذا الدّرس خاصّ بالإصدار الثاني من بايثون (Python 2.x). تثبيت وتفعيل بيئة وهميةسنثبت حزمة virtualenv لعزل مشروع بايثون الخاص بنا من بيئة بايثون الخاصة بالنظام. يمكننا فعل هذا بسهولة عبر تنصيب أداة إدارة الحزم الخاصة ببايثون واسمها pip. لتنصيب pip على Ubuntu يكفي تنصيب virtualenv مباشرة، فهي إحدى اعتمادياته: sudo apt-get update sudo apt-get install python-virtualenv بالنسبة لأنظمة OS X و Windows يمكن تنصيبه بتنصيب pip ثم تنصيب virtualenv عبرها: أو احفظ هذا الملف على جهازك، ثم نفذ الأمر التالي على نافذة الأوامر بالنسبة لـ Windows أو Terminal بالنسبة لـِ Mac OS X، في كلا النظامين، ستحتاج أن تنفذ الأمر التالي بصلاحيات المدير: python get-pip.pyبرنامج virtualenv عبارة عن بيئة وهمية لبايثون لتنصيب مكتبات بايثون في معزل عن بيئة بايثون الحقيقية على النظام، هذا مهم جدا لعزم اعتماديات مشروع الويب الخاص بك وما يحتاجه من حزم عن الحزم العامة المنصبة على كافة النظام، تحتوي بيئة مشاريع بايثون الخاصة بنا على حزمنا فقط، لكي لا تؤثر على نظام التشغيل ككل. سننشئ مجلد المشاريع projects في مجلد Home أو ماشابه، ثم نقوم بإنشاء بيئة وهمية في هذا المجلد، بالنسبة لـ Windows يمكن تنفيذ هذه الأوامر باستخدام طرفية PowerShell: mkdir ~/projects cd ~/projects virtualenv --no-site-packages venv هذا سينشئ مجلدا باسم venv داخل مجلد المشاريع. لقد تُبِّتت بعض أدوات بايثون داخل هذا المجلد وأنشِئَت بنية مجلد لتثبيت أدوات إضافية. يجب علينا تفعيل البيئة الوهمية قبل بداية العمل على مشروعنا : source venv/bin/activateالأمر المُخرَج سيتغير لعكس حقيقة أننا نقوم بعمليات داخل بيئة وهمية الآن. وسيكون كالتالي: (venv)user@Hostname:~/projects$إذا أردت الخروج من البيئة الوهمية، يمكنك في أي وقت كتابة الأمر التالي : deactivateملاحظة: لا تخرج من البيئة الوهمية حاليا. تثبيت Bottleأداة pip تُمكنك من تثبيت حزم بايثون بسهولة من دليل حزم بايثون Python package index، وهو مستودع مُفهرس لمكتبات بايثون. إذا أردنا البحث عن حزم بايثون المتعلقة بـِ Bottle، يمكن تنفيذ: pip search bottleسنبدأ بتثبيت حزمة Bottle فقط: pip install bottleبعد إنتهاء العملية، سنتمكن من استخدام إطار Bottle داخل تطبيقاتنا. إنشاء أول تطبيق باستخدام Bottleكمعظم الأطر، Bottle يطبق نسخة من النمط البرمجي MVC .MVC اختصار لـِ Model, view, controller نموذج،عرض،هيكل؛ وهو أمر للفصل بين عوامل مختلفة بين واجهة المستخدم والمنطق البرمجي. النموذج model تمثيل لمجموعة من البيانات وهو مسؤول عن تخزين، استعلام، وتحديث البيانات.العرض view مسؤول عن كيفية تقديم المعلومة للمستخدم. ويُستخدم لتشكيل وضبط عرض البيانات.الهيكل controller هو مركز العمليات الرئيسي للتطبيق، والذي يقرر كيفية الإجابة لطلبات المستخدم.تطبيقات bottle يمكنها أن تكون بسيطة للغاية. في شكلها البسيط يمكنها تنفيذ جميع المكونات في ملف واحد. سنقوم بإنشاء تطبيق "مرحبا بالعالم" لعرض كيفية العمل. باستعمال محررك المفضل (في هذه الحالة سنستعمل محرر سطر الأوامر nano، بالنسبة لنظام Windows يمكنك استعمال محرر مرئي)، أنشئ تطبيق بايثون باسم hello.py: nano hello.pyفي هذا الملف، سنقوم أولا باستدعاء بعض الوظائف من حزمة Bottle. الأمر الذي سيمكننا من استخدام أدوات الإطار داخل تطبيقنا: from bottle import route, runهذا السطر يخبر برنامجنا بأننا نحتاج إلى استيراد المسار route وتشغيل النماذج modules من حزمة Bottle. نموذج run الذي قمنا باستيراده يمكن أن يُستعمل لتشغيل التطبيق في خادوم التطوير، الشيء الذي يعتبر جيداً لرؤية نتائج برنامجك بسرعة. نموذج route مسؤول عن إخبار التطبيق بالتعامل مع أي من طلباتURL باستخدام أي من دوال بايثون.تطبيقات Bottle تنفّذ التوجيه routing باستدعاء دالّة بايثون واحدة لكلّ طلب من طلبات URL. وتقوم بعد ذلك بإرجاع نتائج الدالة للمُستخدم. نستطيع إضافة توجيه سيُوافق رابط URL /hello from bottle import route, run @route('/hello')هذا التوجيه سيوافق رابط URL /hello عندما يتمّ طلب هذا المسار على الخادوم. ستُنفّذ الدّالة التّابعة مباشرة: # -*- coding: utf-8 -*- from bottle import route, run @route('/hello') def hello(): return u"<h1>مرحباً بالعالم</h1>"ملاحظات: السطر # -*- coding: utf-8 -*- مسؤولٌ عن دعم اليونيكود وبالتالي اللغة العربية، فهو يخبر مفسر بايثون أن هذا الملف به أحرف unicode غير الأحرف الانجليزية.حرف u (اختصارًا لـ unicode) قبل النص العربي مهم أيضا لإخبار بايثون أن هذه السلسلة النصية بالضبط تحتوي على أحرف يونيكود وبالتالي يعامل السلسلة النصية بطريقة خاصة.هذه الدّالة بسيطة جدّاً، لكنّها كافية لإكمال المتطلّب الوحيد لدالّة توجيه: تقوم بإرجاع قيمة يُمكن عرضها على المتصفّح. في هذه الحالة، القيمة عبارة عن نص HTML. يمكننا حذف وسم h1 وستُعرض نفس القيمة بشكل غير منسّق. أخيراً، نحتاج إلى تشغيل تطبيقنا باستعمال خادوم التّطوير development server: # -*- coding: utf-8 -*- from bottle import route, run @route('/hello') def hello(): return u"<h1>مرحباً بالعالم</h1>" run(host='0.0.0.0', port=8080)هذا السطر سيُشغل الخادوم. بتمرير المعامل 'host='0.0.0.0 الأمر سيقوم بإرجاع المحتوى لأي حاسوب، وليس فقط الحاسوب المحليّ. هذا مهم بما أن تطبيقنا مستضاف عن بعد. معامل port يقوم بتحديد المنفذ الذي سنستخدمه. يُمكننا تشغيل التطبيق بتنفيذ الأمر: python hello.pyيمكنك زيارة التطبيق بمتصفح الويب عن طريق الذهاب إلى عنوان IP الخاصّ بك (إن كنت تعمل على خادوم) أو localhost إن كنت تعمل محليا، متبوعاً برقم المنفذ الذي قمنا باختياره (8080)، متبوعا بالتوجيه الذي أنشأناه (hello/): http://localhost:8080/helloسيظهر لك التالي: يُمكن إيقاف الخادوم في أي وقت بالضغط على CTRL-C في نافذة الطرفيّة أو سطر الأوامر. تطبيق مبدأ MVCلقد نفّذنا الآن تطبيقنا الأول. لقد كان بسيطاً بالتأكيد، ولكنّه لا ينفّذ مبادئ MVC، أو لا يقوم بشيء مثير للاهتمام. لنحاول جعله تطبيقاً أكثر تعقيداً هذه المرّة. إنشاء النموذجلنبدأ بنموذجنا، هذا هو الجزء الخاص بالتّعامل مع تخزين البيانات في برنامجنا. يمكن لـ Bottle بسهولة استخدام مجموعة من الواجهات الخلفية backends للبيانات باستعمال الإضافات. سنستخدم ملف SQLite لقاعدة بيانات التطبيق. هذه قاعدة بيانات بسيطة للغاية مُصمّمة للعمليّات الخفيفة التي يُمكن أن يقوم بها برنامجنا. ثبّت أولا SQLite، على Ubuntu يمكن ذلك عبر الأمر التالي: sudo apt-get install sqliteبالنسبة لـ Windows و OS X يمكن تثبيتها من على موقعها الرسمي. نحتاج كذلك إلى تحميل وتثبيت إضافة Bottle التي تُخوّلنا لاستعمال قواعد البيانات هذه: pip install bottle-sqliteالآن نحن نمتلك المكوّنات الأساسية، نستطيع أن ننشئ قاعدة بيانات بسيطة لتخزين بياناتنا فيها. سنقوم بإنشاء ملفّ بايثون لتوليد قاعدة بيانات SQLite مع بعض البيانات بداخلها عندما ننفّذ الملفّ. يُمكننا فعل الأمر على مترجم بايثون، لكنّ هذه الطريقة تجعل الأمر أسهل للتكرار. سننشئ ملفا باسم picnic_data.py. nano picnic_data.pyهنا نقوم باستيراد حزمة SQLite. بعد ذلك، يمكننا تنفيذ أمر يُنشئ جدولا ويدخل بيانات فيه. وفي الأخير، ننّفذ التغييرات: # -*- coding: utf-8 -*- import sqlite3 db = sqlite3.connect('picnic.db') db.execute("CREATE TABLE picnic (id INTEGER PRIMARY KEY, item CHAR(100) NOT NULL, quant INTEGER NOT NULL)") db.execute("INSERT INTO picnic (item,quant) VALUES ('خبز' , 4')") db.execute("INSERT INTO picnic (item,quant) VALUES ('جبن', 2)") db.execute("INSERT INTO picnic (item,quant) VALUES ('عنب', 30)") db.execute("INSERT INTO picnic (item,quant) VALUES ('كعك', 1)") db.execute("INSERT INTO picnic (item,quant) VALUES ('مشروبات', 4)") db.commit()احفظ الملفّ وأغلقه يُمكننا تنفيذ الملفّ، الشيء الذي سينشئ ملفّ قاعدة بيانات باسم نزهة.db داخل المُجلّد: python picnic_data.py نموذج تطبيقنا الآن مكتمل. يمكننا الآن استنتاج أن النموذج يملي على التطبيق كيفية تعامل جزء التحكم مع البيانات. إنشاء هيكل التّطبيقبعد أن أنشأنا قاعدة بيانات التّطبيق، يمكننا البدء في تطوير تطبيقنا الرئيسي. هذه العمليّة ستكون وظيفة الهيكل بشكل أساسي. وسيكون الملفّ الأكثر شبها بتطبيقنا الأول. أنشئ ملفّا باسم picnic.py لحفظ تطبيقنا الرئيسي: nano picnic.pyداخل هذا الملفّ، نحتاج إلى استيراد بعض الأشياء من حزمة Bottle، تماما كما سبق. نحتاج إلى بعض النّماذج الإضافية التي لم يسبق لنا أن استخدمناها. إضافة إلى ذلك، نحتاج إلى استيراد وظيفة SQLite: # -*- coding: utf-8 -*- import sqlite3 from bottle import route, run, templateتالياً، سنقوم بتعريف توجيه يوافق مسار URL على الشكل التالي picnic/: # -*- coding: utf-8 -*- import sqlite3 from bottle import route, run, template @route('/picnic')سنضيف دالّة للاتصال بقاعدة البيانات، لتحضر البيانات من الجدول، والاتصال مع العرض View لتقديم الصفحة. وفي الأخير، ستُرجع المخرج إلى المُستخدم. # -*- coding: utf-8 -*- import sqlite3 from bottle import route, run, template @route('/picnic') def show_picnic(): db = sqlite3.connect('picnic.db') c = db.cursor() c.execute("SELECT item,quant FROM picnic") data = c.fetchall() c.close() output = template('bring_to_picnic', rows=data) return outputبعد ذلك سنضيف أمر run لكي نقوم بتشغيل التطبيق: # -*- coding: utf-8 -*- import sqlite3 from bottle import route, run, template @route('/picnic') def show_picnic(): db = sqlite3.connect('picnic.db') c = db.cursor() c.execute("SELECT item,quant FROM picnic") data = c.fetchall() c.close() output = template('bring_to_picnic', rows=data) return output run(host='0.0.0.0', port=8080)احفظ وأغلق الملفّ. نقوم بالاتصال مع قاعدة البيانات باستعمال: db = sqlite3.connect('picnic.db')نقوم باستعلام قاعدة البيانات وجلب جميع القيم بالأسطر الأربعة الموالية. السطر الذي نقوم فيه بالإتصال إلى "العرض" لتشكيل البيانات هو: output = template('bring_to_picnic', rows=data)السطر يقوم بالاتصال بقالب (عرض) باسم bringtopicnic.tpl لتشكيل البيانات وتقديمها. حيث يقوم بتمرير المتغير data لمتغير القالب rows. سنقوم بإنشاء ملفّ القالب هذا في المرحلة التالية. إنشاء العرضالآن نحن نمتلك كلّا من النموذج والهيكل، الشيء الوحيد المتبقّي هو إنشاء العرض. يُمكن القيام بهذا بسهولة بالاستعانة بمحرك القوالب المُدمج مع Bottle. سيبحث التطبيق عن قالب موافق للاسم الذي عرّفناه في الدّالة السابقة، الملفّ يجب أن ينتهي ب .tpl يُمكن للملفّ أن يكون إمّا في مجلّد المشروع، أو داخل مجلّد باسم "view”. أنشئ ملفّا باسم يوافق الاسم الذي عرّفناه في دالّة القالب: nano bring_to_picnic.tplفي هذا الملفّ، يُمكننا دمج HTML والبرمجة معاً. سيكون ملفّنا بسيطا جدّاً. سنقوم باستعمال حلقة تكرار لإنشاء جدول يقوم بعرض بيانات النّموذج: <html dir="rtl" style="font:droid arabic naskh"> <body> <h1>أشياء لإحضارها إلى النّزهة</h1> <table> <tr><th>المكوّن</th><th>الكميّة</th></tr> %for row in rows: <tr> %for col in row: <td>{{col}}</td> %end </tr> %end </table> </body> </html>هذه الأسطر ستقوم بتقديم صفحتنا بصيغة HTML. لغة القالب التي رأينها هي ببساطة لغة بايثون. متغيّر row الذي قمنا بتمريره إلى القالب مُتاح للاستخدام عند تصميم المُخرجات. يُمكننا كتابة أسطر بايثون بتقديم علامة "%". يُمكننا الوصول إلى المُتغيّرات بداخل HTML باستخدام "{{var}}". احفظ الملفّ وأغلقه. مشاهدة النتائجتطبيقنا مكتملٌ الآن ويمكننا تشغيل الملفّ الرئيسي: python picnic.pyيمكننا رؤية النتائج بزيارة عنوان IP متبوعا برقم المنفذ، متبوعاً بالتوجيه picnic/ http://localhost:8080/picnic ختاماًإلى هذه النقطة، يجب أن تكون قادراً على رؤية كيف يُمكنك بناء تطبيقات معقّدة باستخدام الإطار المُصغر والبسيط Bottle. رغم أنّ أمثلتنا بسيطة، إلا أنّك الآن تستطيع بسهولة أن تطوّر تطبيقات إلى القيام بوظائف متقدّمة. نظام إضافات Bottle يعدّ أيضاً أصلاً مهمّاً. الإضافات مُشارَكةُ بنشاط في المجتمع وإضافة وظائف أكثر تعقيداً لتطبيقك يُمكن أن يُنفّذ بسهولة باستخدام الإضافات. هناك طريقة سهلة للبحث عن الإضافات وهي عن طريق استعمال الأمر: pip search bottleهذا سيُعطيك فكرة عن بعض الإضافات الأكثر شعبية. ترجمة -وبتصرّف- للمقال: How To Use the Bottle Micro Framework to Develop Python Web Apps.
    1 نقطة
×
×
  • أضف...