ابنِ نظام تجارة إلكترونية في ثوانٍ مع TomatoPHP
- نُشر في
- مدة القراءة
- 10 دقائق قراءة
خطوة بخطوة، حوّل تطبيق Laravel جديدًا إلى متجر متكامل مع TomatoPHP: لوحة تحكم وأدوار وCRM ومحافظ ونظام محتوى وقوالب وواجهة متجر جاهزة.
مرحبًا يا مجتمع المطورين.
TomatoPHP مجموعة حديثة ومفتوحة المصدر من حزم Laravel، صُممت لتسهيل التطوير في بيئة VILT stack. تعتمد هذه المنظومة على Splade لإنشاء تطبيقات صفحة واحدة (SPA) حديثة وعالية الأداء باستخدام ملفات Blade فقط، فتجعل تجربة التطوير فعّالة وممتعة في آن واحد.
نواصل تطوير المنظومة بإضافة ميزات جديدة إلى إضافاتنا، وقد بنينا منها الآن نظام تجارة إلكترونية متكاملًا. سأرشدك في هذا المقال خطوة بخطوة خلال التنفيذ كاملًا، لتتمكن من إضافة نظام تجارة إلكترونية قوي إلى تطبيق Laravel الخاص بك.
في النهاية سيكون لديك:
- لوحة تحكم مع إدارة للأدوار
- نظام CRM لعملائك بحارس مصادقة خاص بهم
- محافظ للعملاء ومدفوعات
- نظام إدارة محتوى ونظام قوالب لواجهة المتجر
- منتجات وطلبات وعروض وفروع، مع قالب تجارة إلكترونية جاهز فوقها
ملاحظة: كُتب هذا الدليل في مطلع 2024 لإصدارات TomatoPHP المبنية على Laravel 10. غيّرت إصدارات Laravel الأحدث بعض الملفات المذكورة أدناه (مثل RouteServiceProvider.php والـ middleware المسمى Authenticate)، فعدّل هذه الخطوات إن كنت تستخدم إصدارًا أحدث.
تثبيت Tomato Admin
يبدأ كل شيء من إضافة tomato-admin مثبّتة على تطبيق Laravel جديد.
- أنشئ تطبيق Laravel جديدًا:
composer create-project laravel/laravel tomato
إن لم تكن لديك بيئة لتشغيل Laravel بعد، يمكنك الاستعانة بهذا الدليل لبناء واحدة على Ubuntu Linux.
- انتقل بالأمر
cdإلى مجلد المشروع، واضبط بيانات قاعدة البيانات في ملف.env، وتأكد أن التطبيق يعمل وأن قاعدة البيانات متصلة. أسهل طريقة للتحقق هي تشغيل الـ migrations:
php artisan migrate
- ثبّت tomato-admin:
composer require tomatophp/tomato-admin
- بعد انتهاء Composer شغّل أمر التثبيت التلقائي:
php artisan tomato-admin:install
- إن كنت على macOS فيمكن لأداة التثبيت أن تثبّت حزم Yarn تلقائيًا، وإلا فابنِ ملفات الواجهة بنفسك هكذا:
yarn && yarn build
ملاحظة: كان الأمر في المقال الأصلي yarn & yarn build، والرمز & المفرد يرسل yarn إلى الخلفية، لذلك استُخدم && هنا وفي بقية الدليل.
أصبح tomato-admin مثبّتًا الآن على مشروع Laravel الخاص بك.
نشر ملفات migrations الخاصة بـ Media Library
تستخدم حزمنا ملفات الوسائط، لذلك نحتاج إلى نشر ملفات migrations الخاصة بـ Spatie Media Library:
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-migrations"
إن لم يعمل هذا الأمر فاستخدم النسخة التفاعلية بدلًا منه:

php artisan vendor:publish
ثم اكتب media في مربع البحث واختر عنصر الـ migrations. بعد ذلك نفّذ الـ migrations:
php artisan migrate
افتح المتصفح الآن وستظهر لك صفحة رئيسية مثل هذه:

أخيرًا، غيّر قيمة الثابت HOME في RouteServiceProvider.php إلى /admin، ليُعاد توجيه المستخدمين إلى لوحة التحكم بعد تسجيل الدخول.
تثبيت Tomato Roles
لا يكتمل أي نظام تجارة إلكترونية دون إدارة متينة للأدوار، لذلك الحزمة التالية هي tomato-roles.
- أضف الحزمة:
composer require tomatophp/tomato-roles
- بعد انتهاء Composer شغّل أمر التثبيت:
php artisan tomato-roles:install
- افتح
app\Models\User.phpوأضف إليه هذا الـ trait:
use \Spatie\Permission\Traits\HasRoles;
أصبحت لوحة التحكم جاهزة. سجّل الدخول من /admin/login بالبريد [email protected] وكلمة المرور password.

إن حاولت فتح أي صفحة فأُعيد توجيهك إلى
Two-factor Confirmationولم تكن تحتاجها الآن، يمكنك إيقافها بحذفimplements MustVerifyEmailمن نموذجUser.php.
تثبيت Tomato CRM
يجب أن يدير نظام التجارة الإلكترونية تفاعلات العملاء ومصادقتهم وغيرها من الإجراءات الأساسية، وهذا ما تتولاه tomato-crm.
- أضف الحزمة وثبّتها:
composer require tomatophp/tomato-crm
php artisan tomato-crm:install
- انشر النموذج
Accounts.phpداخل تطبيقك لتتمكن من تخصيصه:
php artisan vendor:publish --tag="tomato-crm-model"
- انشر ملف إعدادات tomato-crm:
php artisan vendor:publish --tag="tomato-crm-config"
- في ملف الإعدادات
tomato-crm.phpوجّه النموذج إلى النسخة الموجودة في تطبيقك:
"model" => \App\Models\Account::class,
إضافة حارس accounts
يسجّل العملاء دخولهم بشكل منفصل عن المشرفين، لذلك نحتاج إلى حارس جديد. أضفه إلى config/auth.php هكذا:
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'accounts' => [
'driver' => 'session',
'provider' => 'accounts',
]
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'accounts' => [
'driver' => 'eloquent',
'model' => App\Models\Account::class,
],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expiry time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
| The throttle setting is the number of seconds a user must wait before
| generating more password reset tokens. This prevents the user from
| quickly generating a very large amount of password reset tokens.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_reset_tokens',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];
ثم امسح ذاكرة الإعدادات المؤقتة وأعد بناء ملفات الواجهة:
php artisan config:clear
yarn && yarn build
أصبح نظام CRM جاهزًا، ويمكنك الاطلاع عليه من لوحة التحكم.
تثبيت Tomato Wallet
لإدارة المعاملات بين العملاء والبائعين تحتاج إلى معالج مدفوعات متين. تدير tomato-wallet محافظ العملاء وتعالج المدفوعات أيضًا، وتأتي مع العديد من بوابات الدفع المدمجة.
- أضف الحزمة وثبّتها:
composer require tomatophp/tomato-wallet
php artisan tomato-wallet:install
- اجعل النموذج
Account.phpيطبّق الواجهةWalletويستخدم الـ trait المسمىHasWalletلتعمل محافظ العملاء. يجب أن يبدو نموذج Account هكذا:
<?php
namespace App\Models;
use Bavix\Wallet\Interfaces\Wallet;
use Bavix\Wallet\Traits\HasWallet;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Macroable\Macroable;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\Permission\Traits\HasRoles;
use TomatoPHP\TomatoCrm\Models\Group;
/**
* @property integer $id
* @property string $name
* @property string $username
* @property string $loginBy
* @property string $address
* @property string $type
* @property string $password
* @property string $otp_code
* @property string $otp_activated_at
* @property string $last_login
* @property string $agent
* @property string $host
* @property integer $attempts
* @property boolean $login
* @property boolean $activated
* @property boolean $blocked
* @property string $deleted_at
* @property string $created_at
* @property string $updated_at
* @property AccountsMeta[] $accountsMetas
* @property Activity[] $activities
* @property Comment[] $comments
* @property Model meta($key, $value)
* @property Location[] $locations
*/
class Account extends Authenticatable implements HasMedia, Wallet
{
use InteractsWithMedia;
use HasApiTokens, HasFactory, Notifiable;
use HasWallet;
/**
* @var array
*/
protected $fillable = [
'email',
'phone',
'parent_id',
'type',
'name',
'username',
'loginBy',
'address',
'password',
'otp_code',
'otp_activated_at',
'last_login',
'agent',
'host',
'is_login',
'is_active',
'deleted_at',
'created_at',
'updated_at'
];
protected $casts = [
'is_login' => 'boolean',
'is_active' => 'boolean'
];
protected $dates = [
'deleted_at',
'created_at',
'updated_at',
'otp_activated_at',
'last_login',
];
protected $appends = [
'birthday',
'gender',
'more'
];
public function getMoreAttribute()
{
$metas = $this->accountsMetas()->get()->pluck('value', 'key')->toArray();
return $metas;
}
public function getBirthdayAttribute()
{
return $this->meta('birthday') ?: null;
}
public function getGenderAttribute()
{
return $this->meta('gender') ?: null;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function accountsMetas()
{
return $this->hasMany('TomatoPHP\TomatoCrm\Models\AccountsMeta');
}
/**
* @param string $key
* @param string|null $value
* @return Model|string
*/
public function meta(string $key, string|null $value=null): Model|string|null
{
if($value){
return $this->accountsMetas()->updateOrCreate(['key' => $key], ['value' => $value]);
}
else {
return $this->accountsMetas()->where('key', $key)->first()?->value;
}
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function activities()
{
return $this->hasMany('TomatoPHP\TomatoCrm\Models\Activity');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function comments()
{
return $this->hasMany('TomatoPHP\TomatoCrm\Models\Comment');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function locations()
{
return $this->hasMany('TomatoPHP\TomatoCrm\Models\Location');
}
public function groups(){
return $this->belongsToMany(Group::class, 'account_groups', 'account_id', 'group_id');
}
}
أصبحت المحفظة تعمل الآن، ويمكنك إجراء أي معاملة ومتابعة رصيد العميل.
تثبيت Tomato CMS
يحتاج كل متجر إلكتروني إلى واجهة أمامية محسّنة جيدًا. ولتحسين محركات البحث (SEO) وإضافة المحتوى كالمقالات والصفحات نستخدم tomato-cms:
composer require tomatophp/tomato-cms
php artisan tomato-cms:install
تثبيت Tomato Themes
تُبنى واجهة المتجر نفسها كقالب باستخدام tomato-themes، وهي حزمة تبسّط المشاريع متعددة القوالب وتعتمد على معمارية Hierarchical Model-View-Controller (HMVC).
- أضف الحزمة وثبّتها، ثم أعد بناء ملفات الواجهة:
composer require tomatophp/tomato-themes
php artisan tomato-themes:install
yarn && yarn build
- تأكد من وجود مجلد
Themesفي جذر المشروع، وأضف مساحة الأسماءThemesإلى قسم autoload فيcomposer.json:
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/",
"Themes\\": "Themes/"
}
},
- أعد تحميل الـ autoloader الخاص بـ Composer:
composer dump-autoload
- أضف ملفات القوالب إلى المصفوفة
contentفيtailwind.config.jsليلتقط Tailwind الأصناف المستخدمة فيها:
content: [
...
"./Themes/**/*.blade.php",
"./Themes/**/**/*.blade.php",
],
أصبح نظام القوالب جاهزًا: يمكنك رفع قالب أو إنشاء قالب جديد.
تثبيت Tomato E-Commerce
بعد أن اكتملت الأسس (CRM وإدارة الأدوار والحزم الداعمة) حان وقت جمعها معًا في نظام التجارة الإلكترونية نفسه.
- أضف الحزمة وثبّتها:
composer require tomatophp/tomato-ecommerce
php artisan tomato-ecommerce:install
تثبّت هذه الحزمة لك tomato-products وtomato-orders وtomato-offers وtomato-branches.
- ليعمل كل شيء كما ينبغي، ثبّت tomato-branches:
php artisan tomato-branches:install
-
أنشئ
Shipping Vendorواحدًا على الأقل من/admin/shipping-vendors. -
اذهب إلى
/admin/settings/seo، وارفع شعاراتك، وغيّر اسم الموقع وبيانات SEO.
تثبيت قالب التجارة الإلكترونية
لنمنح الآن المتجر ونظام إدارة المحتوى مظهرًا جميلًا. يتميز قالبنا بتصميم بسيط وأنيق يمثّل نقطة انطلاق مثالية للتخصيص.
- ادخل إلى مجلد
Themes:
cd Themes
- انسخ قالبنا:
git clone [email protected]:tomatophp/Ecommerce.git
- افتح
/themesفي لوحة التحكم، وستجد القالب الجديد في القائمة، وما عليك إلا تفعيله.
انتبه إلى أن ملف
routes/web.phpالرئيسي يجب ألا يعرّف المسار/، لأنه قد يطغى على مسارات القالب.
- أعد بناء ملفات الواجهة لإصلاح التنسيقات:
yarn && yarn build
افتح صفحتك الرئيسية الآن وستحصل على شيء مثل هذا:

يمكنك اختيار أي قسم من القائمة المنسدلة في الأعلى وإضافته إلى صفحتك.
بناء القوائم
أنشئ قوائمك من /admin/menus باستخدام هذه المسارات:
- الرئيسية
/ - من نحن
/about - المتجر
/shop - المدونة
/blog - اتصل بنا
/contact - الشروط والأحكام
/terms - الخصوصية
/privacy
يمكنك إنشاء قائمتين، main وfooter. تظهر القائمة الرئيسية في الترويسة تلقائيًا، وقائمة التذييل في التذييل.
توجيه الزوار إلى صفحة دخول العملاء
عدّل الـ middleware المسمى Authenticate ليُعاد توجيه الزوار غير المسجلين إلى مسار دخول الحسابات:
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*/
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('accounts.login');
}
}
إضافة traits التجارة الإلكترونية إلى Account
أخيرًا، أضف هذه الـ traits إلى نموذج Account.php:
use \TomatoPHP\TomatoEcommerce\Services\Traits\InteractsWithEcommerce;
use \TomatoPHP\TomatoNotifications\Traits\InteractWithNotifications;
use \TomatoPHP\TomatoOrders\Services\Traits\InteractsWithOrders;
الخلاصة
بعد تثبيت نظام التجارة الإلكترونية كاملًا يمكنك البدء في إدارة كتالوجك: أضف المنتجات، وحدّد التصنيفات لتشكيل ما تعرضه، وأنشئ الطلبات. أصبح النظام جاهزًا لمعالجة المعاملات وتشغيل تجارتك على الإنترنت.
شكرًا لاستخدامك إضافات Tomato وإطار عمل TomatoPHP.
- انضم إلى خادم الدعم على Discord
- اقرأ التوثيق
- إن أعجبك أي مستودع فامنحه نجمة على TomatoPHP GitHub
- ادعمنا عبر GitHub Sponsors