هذا الدرس جزء من سلسلة تعلم 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 ShoppingCart لإضافة هذه الخاصية إلى المشروع. يغطي الدرس المواضيع التالية:
تثبيت حزمة Laravel Shopping Cart بـComposer.
- إعداد Laravel 5 لاستخدام الحزمة.
- إضافة عناصر إلى سلة المشتريات.
- العثور على العناصر الموجودة في سلة المشتريات.
- تحديث عنصر في سلة المشتريات.
- حذف عنصر من سلة المشتريات.
استخدام Composer لتثبيت Laravel Shopping Cart
نفتح ملف composer.json
لإضافة اعتمادية جديدة للمشروع.
نبحث عن فقرة require
:
"require": { "php": ">=5.5.9", "laravel/framework": "5.2.*", "doctrine/dbal": "v2.4.2" },
نضيف حزمة ShoppingCart
على النحو التالي:
"require": { "php": ">=5.5.9", "laravel/framework": "5.2.*", "doctrine/dbal": "v2.4.2", "gloudemans/shoppingcart": "~1.3" },
ملحوظة: انتبه للفواصل في نهاية الأسطر.
نعلم Composer أننا نريد تثبيت الإصدار 1.3 من الحزمة gloudemans/shoppingcart
؛ ثم نحدّث المشروع بتنفيذ الأمر التالي:
composer update
إعداد Laravel لاستخدام حزمة ShoppingCart
نحتاج بعد تثبيت حزمة ShoppingCart لإعداد Laravel للعمل معها. نفتح ملف الإعداد config/app.php
ونضيف السطر التالي إلى مصفوفة providers
:
Gloudemans\Shoppingcart\ShoppingcartServiceProvider::class,
يسجل الإعداد أعلاه مزوّد خدمة Provider لسلة المشتريات.
ملحوظة: يتيح مزود الخدمة Service Provider في Laravel تحميل صنف (في الذاكرة) مع بدء عمل التطبيق، كما أنه يمكِّن من إضافة عناصر جديدة إلى حاويات الخدمة Service container وهي أداة تدير الاعتمادات بين مختلف الأصناف في إطار العمل.
سنضيف الآن كنية Alias لصنف سلة المشتريات. افتح ملف الإعداد config/app.php
وأضف العنصر التالي إلى مصفوفة aliases
:
'Cart' => Gloudemans\Shoppingcart\Facades\Cart::class,
ملحوظة: الكنى Aliases هي أسماء مختصرة للأصناف تُكتب بدلا من الاسم الكامل للصنف. يسجّل التطبيقُ عند بدئه هذه الأصنافَ لكنه لا يحملها إلا عند الحاجة.
إضافة عناصر لسلة المشتريات
سنضيف في هذه الفقرة إمكانية إضافة عنصر إلى سلة المشتريات في صفحة المنتج. تُجرى العملية على ثلاث خطوات:
- إنشاء مسار لإجراء
HTTP POST
الذي يضيف العناصر إلى سلة المشتريات. - التعديل على القالب
products.blade.php
من أجل تضمين استمارة لإرسال البيانات مع معرّف المنتَج. - التعديل على المتحكم
Front.php
لكي يتبقى بيانات الاستمارة ويضيفها إلى السلة.
مسار إجراء HTTP POST
افتح ملف المسارات routes.php
وأضف المسار التالي:
Route::post('/cart', 'Front@cart');
يعرف السطر السابق مسارات لتلقي إجراءات POST
على رابط سلة المشتريات. سيُستخدَم هذا المسار لإضافة عناصر إلى سلة المشتريات.
استمارة صفحة المنتج
الخطوة التالية هي التعديل على قالب صفحة المنتج وإضافة استمارة form
لإرسال معرّف المنتج إلى سلة المشتريات من أجل إضافته إليها. افتح ملف العرض products.blade.php
وعدّله ليصبح محتواه التالي:
@extends('layouts.layout') @section('content') <section id="advertisement"> <div class="container"> <img src="{{asset('images/shop/advertisement.jpg')}}" alt="" /> </div> </section> <section> <div class="container"> <div class="row"> <div class="col-sm-3"> <div class="left-sidebar"> @include('shared.sidebar') </div> </div> <div class="col-sm-9 padding-right"> <div class="features_items"><!--features_items--> <h2 class="title text-center">Features Items</h2> @foreach ($products as $product) <div class="col-sm-4"> <div class="product-image-wrapper"> <div class="single-products"> <div class="productinfo text-center"> <img src="{{asset('images/shop/product9.jpg')}}" alt="" /> <h2>${{$product->price}}</h2> <p>{{$product->name}}</p> <a href="{{url('cart')}}" class="btn btn-default add-to-cart"><i class="fa fa-shopping-cart"></i>Add to cart</a> <a href='{{url("products/details/$product->id")}}' class="btn btn-default add-to-cart"><i class="fa fa-info"></i>View Details</a> </div> <div class="product-overlay"> <div class="overlay-content"> <h2>${{$product->price}}</h2> <p>${{$product->name}}</p> <form method="POST" action="{{url('cart')}}"> <input type="hidden" name="product_id" value="{{$product->id}}"> <input type="hidden" name="_token" value="{{ csrf_token() }}"> <button type="submit" class="btn btn-fefault add-to-cart"> <i class="fa fa-shopping-cart"></i> Add to cart </button> </form> <a href='{{url("products/details/$product->id")}}' class="btn btn-default add-to-cart"><i class="fa fa-info"></i>View Details</a> </div> </div> </div> <div class="choose"> <ul class="nav nav-pills nav-justified"> <li><a href=""><i class="fa fa-plus-square"></i>Add to wishlist</a></li> <li><a href=""><i class="fa fa-plus-square"></i>Add to compare</a></li> </ul> </div> </div> </div> @endforeach <ul class="pagination"> <li class="active"><a href="">1</a></li> <li><a href="">2</a></li> <li><a href="">3</a></li> <li><a href="">»</a></li> </ul> </div><!--features_items--> </div> </div> </div> </section> @endsection
التغيير الأساسي هنا هو إضافة استمارة form
مع إجراء post
:
<form method="POST" action="{{url('cart')}}">...</form>
تُرسل الاستمارة معرف المنتج إلى سلة المشتريات الذي يعرفه حقل product_id
:
<input type="hidden" name="product_id" value="{{$product->id}}">
تحتوي الاستمارة أيضا على عنصر أمني هو:
<input type="hidden" name="token" value="{{ csrftoken() }}">
الذي يعرف رمز أمان Security token للحماية ضد هجمات تزوير الطلب عبر الموقع Cross-site request forgery (تُكتب CSRF أو XCRF اختصارا).
احفظ التعديلات.
ملحوظة: تقوم هجمات تزوير الطلب عبر الموقع على البحث عن روابط تمكن إعادة استخدامها لتنفيذ إجراءات معينة تحتاج لصلاحيات خاصة، تتوفر عادة عند المستخدمين المسجلين، ثم الاحتيال عليهم لكي يفتحوا هذه الروابط - غالبا دون علمهم - وتنفيذ الإجراءات الطلوبة. تحمي رموز الأمان المستخدمين من هذه الهجمات.
التعديل على المتحكم Front
نحتاج، ليمكن لنا استخدام سلة المشتريات، التعديل على دالة cart
لاستيرد فضاء الأسماء Cart
. افتح ملف المتحكم Front.php
وأضف الأسطر التالية لاستيراد فضاءات الأسماء Redirect
، Request
وCart
على التوالي:
يُستخدَم Request
للوصول إلى بيانات إجراءات HTTP.
- يُستخدَم
Redirect
لتوجيه المستخدم بعد تنفيذ عملية لا تحتاج لإظهار بيانات في الصفحة. - للوصول إلى عناصر سلة المشتريات نستخدم
Cart
.
اعثُر على الدالة cart
في المتحكم Front.php
وحدّثها كالتالي:
public function cart() { if (Request::isMethod('post')) { $product_id = Request::get('product_id'); $product = Product::find($product_id); Cart::add(array('id' => $product_id, 'name' => $product->name, 'qty' => 1, 'price' => $product->price)); } $cart = Cart::content(); return view('cart', array('cart' => $cart, 'title' => 'Welcome', 'description' => '', 'page' => 'home')); }
نفحص أولا نوع إجراء HTTP الذي أتى منه الطلب إلى الدالة:
if if (Request::isMethod(‘
فإن كان الإجراء من نوع POST
ننفذ الشفرة الموالية.
نعثر علي معرف المنتج المُرسَل في الطلب:
$productid = Request::get('productid');
دالة Request::get
لا تتعلق بنوعية إجراء HTTP ويتساوى عندها POST
وGET
. تُستخدَم هذه الدالة للعثور على متغيرات مرسلة في الطلب.
نستخدم نموذج المنتج Product
للعثور على المنتج في قاعدة البيانات:
$product = Product::find($product_id);
نستخدم كائن المنتج في التعليمة السابقة للحصول على بيانات المنتج وإضافتها إلى سلة المشتريات بإرسال نداء إلى الدالة Cart::add
:
Cart::add(array('id' => $product_id, 'name' => $product->name, 'qty' => 1, 'price' => $product->price));
ننادي الدالة Cart::content
للحصول على محتوى سلة المشتريات ونضيفه إلى المتغيرات الممررة إلى العرض cart.blade.php
:
$cart = Cart::content(); return view('cart', array('cart' => $cart, 'title' => 'Welcome', 'description' => '', 'page' => 'home'));
العثور على العناصر الموجودة في سلة المشتريات
بقيت لنا خطوة واحدة قبل أن نستطيع تجربة سلة المشتريات. نحتاج لتعديل العرض cart
لكي يُظهر محتويات السلة. نفتح ملف العرض cart.blade.php
لتحريره. نعدّل الملف على النحو التالي:
@extends('layouts.layout') @section('content') <section id="cart_items"> <div class="container"> <div class="breadcrumbs"> <ol class="breadcrumb"> <li><a href="#">Home</a></li> <li class="active">Shopping Cart</li> </ol> </div> <div class="table-responsive cart_info"> @if(count($cart)) <table class="table table-condensed"> <thead> <tr class="cart_menu"> <td class="image">Item</td> <td class="description"></td> <td class="price">Price</td> <td class="quantity">Quantity</td> <td class="total">Total</td> <td></td> </tr> </thead> <tbody> @foreach($cart as $item) <tr> <td class="cart_product"> <a href=""><img src="images/cart/one.png" alt=""></a> </td> <td class="cart_description"> <h4><a href="">{{$item->name}}</a></h4> <p>Web ID: {{$item->id}}</p> </td> <td class="cart_price"> <p>${{$item->price}}</p> </td> <td class="cart_quantity"> <div class="cart_quantity_button"> <a class="cart_quantity_up" href=""> + </a> <input class="cart_quantity_input" type="text" name="quantity" value="{{$item->qty}}" autocomplete="off" size="2"> <a class="cart_quantity_down" href=""> - </a> </div> </td> <td class="cart_total"> <p class="cart_total_price">${{$item->subtotal}}</p> </td> <td class="cart_delete"> <a class="cart_quantity_delete" href=""><i class="fa fa-times"></i></a> </td> </tr> @endforeach @else <p>You have no items in the shopping cart</p> @endif </tbody> </table> </div> </div> </section> <!--/#cart_items--> <section id="do_action"> <div class="container"> <div class="heading"> <h3>What would you like to do next?</h3> <p>Choose if you have a discount code or reward points you want to use or would like to estimate your delivery cost.</p> </div> <div class="row"> <div class="col-sm-6"> <div class="chose_area"> <ul class="user_option"> <li> <input type="checkbox"> <label>Use Coupon Code</label> </li> <li> <input type="checkbox"> <label>Use Gift Voucher</label> </li> <li> <input type="checkbox"> <label>Estimate Shipping & Taxes</label> </li> </ul> <ul class="user_info"> <li class="single_field"> <label>Country:</label> <select> <option>United States</option> <option>Bangladesh</option> <option>UK</option> <option>India</option> <option>Pakistan</option> <option>Ucrane</option> <option>Canada</option> <option>Dubai</option> </select> </li> <li class="single_field"> <label>Region / State:</label> <select> <option>Select</option> <option>Dhaka</option> <option>London</option> <option>Dillih</option> <option>Lahore</option> <option>Alaska</option> <option>Canada</option> <option>Dubai</option> </select> </li> <li class="single_field zip-field"> <label>Zip Code:</label> <input type="text"> </li> </ul> <a class="btn btn-default update" href="">Get Quotes</a> <a class="btn btn-default check_out" href="">Continue</a> </div> </div> <div class="col-sm-6"> <div class="total_area"> <ul> <li>Cart Sub Total <span>$59</span></li> <li>Eco Tax <span>$2</span></li> <li>Shipping Cost <span>Free</span></li> <li>Total <span>${{Cart::total()}}</span></li> </ul> <a class="btn btn-default update" href="{{url('clear-cart')}}">Clear Cart</a> <a class="btn btn-default check_out" href="{{url('checkout')}}">Check Out</a> </div> </div> </div> </div> </section><!--/#do_action--> @endsection
نستخدم الدالة count
لتحديد ما إذا كان المتغير cart
يحوي أي عناصر، فإن كان أنشأنا جدولا لعرض عناصر سلة المشتريات ديناميكيا:
@if(count($cart)) <table class="table table-condensed">
نستخدم الحلقة التكرارية foreach
لعدّ عناصر سلة المشتريات:
@foreach(item)
لكل منتج في سلة المشتريات نعرض اسم المنتج، معرّفه، ثمنه ومجموعا فرعيا Subtotal لتكلفة المنتج على التوالي:
{{$item->name}} {{$item->id}} {{$item->price}} {{$item->subtotal}}
المجموع الفرعي هو حاصل ضرب ثمن المنتج بكميّته. في الأسفل نعرض الثمن الكلي للمنتجات الموجودة في سلة المشتريات:
{{Cart::total()}}
تحديث العناصر الموجودة في سلة المشتريات
نضيف في هذه الفقرة إمكانية تحديث كمية المنتج في سلة المشتريات بالنقر على زر الزيادة +
أو النقصان -
بجانب الكمية. سنستخدم لهذا الغرض الاستعلام عن طريق رابط URL.
افتح ملف العرض cart.blade.php
واعثر على السطرين:
<a class="cart_quantity_up" href=""> + </a> <a class="cart_quantity_down" href=""> - </a>
حدّث الشفرة المصدرية لكل منهما حتى تصبح على النحو التالي:
<a class="cart_quantity_up" href='{{url("cart?product_id=$item->id&increment=1")}}'> + </a> <a class="cart_quantity_down" href='{{url("cart?product_id=$item->id&decrease=1")}}'> - </a>
تولد الشفرة:
{{url("cart?productid=$item->id&increment=1")}}
رابطا بالهيئة http://larashop.dev/cart?productid=1&increment=1
. يعيّن الرابط معرّف المنتج الذي نريد تحديث كميته واتجاه التحديث. إذا كان المتسوق يريد زيادة الكمية (نقر على +
) نعطي القيمة 1
للمعطى increment
؛ أما إذا كان المتسوق يريد نقص الكمية (نقر على -
) فنعطي القيمة 1
للمتغير decrease
.
يجب الآن تعديل المتحكم للتعاطي مع رغبة المتسوق في تحديث الكمية. نعدل الدالة cart
لتصبح على النحو التالي:
public function cart() { // إضافة منتج جديد إلى سلة المشتريات if (Request::isMethod('post')) { $product_id = Request::get('product_id'); $product = Product::find($product_id); Cart::add(array('id' => $product_id, 'name' => $product->name, 'qty' => 1, 'price' => $product->price)); } // زيادة كمية منتج في سلة المشتريات if (Request::get('product_id') && (Request::get('increment')) == 1) { $rowId = Cart::search(array('id' => Request::get('product_id'))); $item = Cart::get($rowId[0]); Cart::update($rowId[0], $item->qty + 1); } // نقص كمية منتج في سلة المشتريات if (Request::get('product_id') && (Request::get('decrease')) == 1) { $rowId = Cart::search(array('id' => Request::get('product_id'))); $item = Cart::get($rowId[0]); Cart::update($rowId[0], $item->qty - 1); } $cart = Cart::content(); return view('cart', array('cart' => $cart, 'title' => 'Welcome', 'description' => '', 'page' => 'home')); }
في الشيفرة أعلاه نتحقق من تعيين المتغيّرين product_id
وincrement
.
if (Request::get('product_id') && (Request::get('increment')) == 1)
إذا كان المتغيران معيَّنيْن وقيمة المتغيّر increment
تساوي 1
فهذا يعني أن المتسوق أراد زيادة الكمية.
يستخدم السطر الموالي معرّف المنتج product_id
للبحث بين عناصر سلة المشتريات ويرجع مصفوفة بمعرّفات أسطُر rowId
موافقة للبحث:
$rowId = Cart::search(array('id' => Request::get('product_id')));
معرّف السطر هو معرّف وحيد لعنصُر في السلة يُولّد تلقائيا، ويُستخدَم لتحديث العناصر في السلة. نستخدم معرف العنصر للعثور على كائن يمثل المنتج في سلة المشتريات:
$item = Cart::get($rowId[0]);
نحتفظ بالعنصر الأول من المصفوفة التي ترجعها الدالة Cart::get
، في حالتنا لا يوجد سوى عنصر واحد. نبحث عن كائن المنتج لمعرفة الكمية الموجودة في السلة وبالتالي يمكن لنا زيادتها أو نقصها.
نستدعي الدالة Cart::update
ونمرر لها معرف المنتج ونزيد الكمية بـ1
:
Cart::update($rowId[0], $item->qty + 1);
السطر الموالي يتحقق من تعيين المتغيرين product_id
وdecrease
:
if (Request::get('productid') && (Request::get('decrease')) == 1)
وفي حال كانت الإجابة نعم يفحص قيمة المتغير decrease
وإذا كانت 1
ينقص كمية المنتج بـ1
في سلة المشتريات:
Cart::update($rowId[0], $item->qty 1);
افتح رابط صفحة المنتجات http://larashop.dev/products
، اختر أحدها بتمرير المؤشر فوقه وأضفه إلى سلة المشتريات بالنقر على زر Add to cart.
ستحصل على النتيجة التالية (تتغير النتيجة حسب المنتج الذي اخترته في الخطوة السابقة).
اضغط على الزر +
لزيادة كمية منتج في سلة المشتريات. لاحظ تغير المجموع الفرعي مع تغير الكمية.
حذف عناصر من سلة المشتريات
حذفُ عنصُر من سلة المشتريات مشابه لتحديثه:
$rowId = Cart::search(array('id' => Request::get('product_id'))); Cart::remove($rowId[0]);
تحذف الدالة Cart::remove
عنصرا من سلة المشتريات اعتمادا على معرف السطر الممرَّر إليها.
لحذف جميع عناصر سلة المشتريات دفعة واحدة نستخدم الدالة Cart::destroy
.
خاتمة
كان الهدف من هذا الدرس شرح كيفية تثبيت حزمة Laravel ShoppingCart واستخدامها في مشروع Laravel الخاص بك للحصول على ميزة سلة مشتريات. استعملنا خلال هذا الدرس الحزمة في صفحة المنتج، يمكنك التوسع في استخدام الحزمة في صفحات الموقع الأخرى إن أردت.
ترجمة -وبتصرّف- لمقال Laravel 5 Shopping Cart لصاحبه Rodrick Kazembe.
أفضل التعليقات
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.