دمج React مع Laravel يمكن أن يعزز تجربة المستخدم من خلال الجمع بين قدرة Laravel على إدارة الخلفية (Back-end) وقوة React في بناء الواجهات الأمامية (Front-end)
لإنشاء تطبيق Chirps
react js and laravel 11 for chirps
المتطلـــــــــــــــــبات
composer
Laravel يعتمد على مدير الحزم Composer يمكنك تحميلة من موقعه الرسمي: https://getcomposer.org/download
Visual Studio Code
فيجوال ستوديو كود (Visual Studio Code) هو برنامج تحرير النصوص بيئة تطوير مفتوحة المصدر وخفيفة الوزن تم تطويرها بواسطة مايكروسوفت. تعتبر أحد أشهر وأكثر الأدوات شعبية بين المطورين لتطوير البرمجيات وتحرير النصوص بفضل ميزاتها القوية والمرونة التي توفرها.
- قم بزيارة موقع فيجوال ستوديو كود.
- يمكنك الرجوع للمقال الخاص بة لمعرفة المزيد.
Node js
تاكد من تثبيت برنامج Node js والافضل يكون احدث اصدار او انتقل إلى موقع Node.js الرسمي وحمّل المثبت المناسب لنظام Windows الخاص بك
تثبيت لارافيل 11 Laravel
هذه الخطوة تستخدم composer لإنشاء مشروع Laravel جديد باسم  chirper
				
					composer create-project laravel/laravel chirper 
				
			بعد إنشاء المشروع، انتقل إلى دليل المشروع باستخدام الأمر cd chirper
بمجرد بدء تشغيل خادم تطوير Artisan، سيكون بإمكانك الوصول إلى التطبيق الخاص بك في متصفح الويب الخاص بك على http://localhost:8000 .
				
					cd chirper
php artisan serve 
				
			تثبيت Installing Laravel Breeze
هذه الخطوة تثبت حزمة Laravel Breeze، وهي حزمة توفر إعدادات بسيطة لتسجيل الدخول والعمليات الأخرى المتعلقة بالمصادقة
				
					composer require laravel/breeze --dev 
				
			هذه الخطوة تستخدم Laravel Artisan لتثبيت React باستخدام Breeze
				
					php artisan breeze:install react 
				
			سيقوم Breeze بتثبيت وتكوين تبعيات الواجهة الأمامية لك، لذلك نحتاج فقط إلى تشغيل خادم تطوير Vite أثناء إنشاء تطبيقنا
هذه الخطوة تستخدم npm لتجميع الأصول الأمامية وتحديثها
تاكد من تثبيت احدث نسخة من برنامج node.js قبل تنفيذ الامر لعدم حدوث مشاكل
				
					npm run dev 
				
			Models, migrations, and controllers
إنشاء نموذج ومهاجرات، ووحدة تحكم للـ Chirps عن طريق الكود التالي
				
					php artisan make:model -mrc Chirp 
				
			وبهذا قمنا بانشاء 3 ملفات وهم :
- نموذج او موديل داخل الرابط app/Models/Chirp.php
- انشاء جدول داخل قاعدة البيانات في الرابط database/migrations/<timestamp>_create_chirps_table.php
- انشاء وحدة تحكم في الرابط app/Http/Controllers/ChirpController.php
migrations
بطبيعة الحال يقوم لارافيل 11 انشاء قاعدة بيانات من نوع SQLite سنقوم بتغييرها الي Mysql بفتح ملف env. والتعديل علية بالشكل التالي
				
					DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=chirper_db
DB_USERNAME=root
DB_PASSWORD= 
				
			بعد تعديل ملف env. نقوم بتحديث ملف database/migrations/<timestamp>_create_chirps_table.php بالشكل الاتي:
				
					public function up(): void
    {
        Schema::create('chirps', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('message');
            $table->timestamps();
        });
    } 
				
			بعد ذلك نقوم بترحيل البيانات الي قاعدة البيانات التي سيتم انشاءها ايضا كالاتي
نقوم باستخدام الامر
				
					php artisan migrate 
				
			ستظهر رسالة ان لايوجد قاعدة بيانات في mysql هي تريد انشاء قاعدة بيانات جديدة باسم chirper_db بهذا الشكل
ستقوم باختيار yes لانشاء قاعدة بيانات وايضا الجداول المذكورة جميعا داخلها وتكون النتيجة بهذا الشكل
Models
سوف نقوم بالتعديل علي النماذج او الموديل الموجودة User , Chirp بالشكل الاتي
اضافة هذا الكود الي نموذج User
				
					//app/Models/User.php
use Illuminate\Database\Eloquent\Relations\HasMany;
 public function chirps(): HasMany
    {
        return $this->hasMany(Chirp::class);
    } 
				
			ثم اضافة هذا الكود الي نموذج Chirp
				
					//app/Models/Chirp.php
  protected $fillable = [
        'message',
    ]; 
				
			controllers
يجب تحديث ملف كونترولر controller هذه الخطوة تضيف منهجية index إلى وحدة التحكم، ولكن ستتم إعادة كتابة الكود لاحقًا 
				
					
				 
			Routing التوجيه
سوف نقوم بتحديث ملف web.php داخل routes باضافة الاكواد التالية:
				
					use App\Http\Controllers\ChirpController;
Route::resource('chirps', ChirpController::class)
    ->only(['index', 'store'])
    ->middleware(['auth', 'verified']); 
				
			Inertia
				
					//app/Http/Controllers/ChirpController.php
namespace App\Http\Controllers;
 
use App\Models\Chirp;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
 
class ChirpController extends Controller
{
    public function index(): Response
    {
        return Inertia::render('Chirps/Index', [
            //
        ]);
    }
 ...
} 
				
			انشاء ملف Chirps/Index
Chirps/Index للواجهة الأمامية الخاص بنا وذلك للرابط resources/js/Pages/Chirps/Index.jsx ونسخ الكود التالي للصفحة مع شرح كل سطر في الكود
				
					//resources/js/Pages/Chirps/Index.jsx
import React from 'react';
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import InputError from '@/Components/InputError';
import PrimaryButton from '@/Components/PrimaryButton';
import { useForm, Head } from '@inertiajs/react';
 
     
				
			- React: المكتبة الأساسية لبناء واجهات المستخدم.
- AuthenticatedLayout: مكون تخطيط (Layout) يستخدم لعرض الصفحات عندما يكون المستخدم مسجل الدخول.
- Chirp: مكون لعرض كل “chirp” (تغريدة).
- InputError: مكون لعرض أخطاء الإدخال.
- PrimaryButton: مكون لعرض زر رئيسي.
- useForm,- Head: دوال ومكونات من Inertia.js للتعامل مع النماذج وتعيين عنوان الصفحة.
				
					export default function Index({ auth }) {
 
				
			- Index: مكون React الرئيسي الذي يتم تصديره. يستقبل- auth(بيانات المستخدم المصادق) و- chirps(قائمة بالتغريدات) كخصائص (props).
				
					    const { data, setData, post, processing, reset, errors } = useForm({
        message: '',
    });
 
				
			- useForm: هو hook من Inertia.js لإدارة حالة النموذج. يتم تهيئة النموذج بحقل- messageفارغ.
- data: يحتوي على بيانات النموذج.
- setData: دالة لتحديث بيانات النموذج.
- post: دالة لإرسال بيانات النموذج.
- processing: حالة توضح ما إذا كان النموذج يتم معالجته.
- reset: دالة لإعادة تعيين بيانات النموذج.
- errors: يحتوي على أخطاء الإدخال إن وجدت.
				
					    const submit = (e) => {
        e.preventDefault();
        post(route('chirps.store'), { onSuccess: () => reset() });
    };
 
				
			- submit: دالة تُستدعى عند إرسال النموذج. تمنع السلوك الافتراضي للمتصفح وترسل البيانات إلى المسار- chirps.store. بعد النجاح، يتم إعادة تعيين النموذج.
				
					    return (
        
             
 
				
			- AuthenticatedLayout: يغلف المكون الرئيسي ويوفر تخطيطًا للمستخدم المصادق عليه.
- Head: يحدد عنوان الصفحة.
				
					            
                   
            
        
    );
}
 
				
			- form: يحتوي على نموذج لإرسال تغريدة جديدة.
- textarea: حقل نص لإدخال التغريدة. يتم تحديث قيمته باستخدام- setData.
- InputError: يعرض أي أخطاء إدخال.
- PrimaryButton: زر لإرسال النموذج.
- الآن بعد أن تم تشغيل الواجهة الأمامية لدينا بواسطة JavaScript، سيتم إعادة تحميل أي تغييرات نجريها على قوالب JavaScript تلقائيًا في المتصفح عندما يتم تشغيل خادم تطوير Vite عبر npm run dev.
				
					npm run dev 
				
			Navigation menu
نقوم بتعديل div داخل الرابط resources/js/Layouts/AuthenticatedLayout.jsx ليناسب العمل علي الشاشات المختلفة للديسك توب وايضا للتليفون
				
					// resources/js/Layouts/AuthenticatedLayout.jsx
// for desktop
    
        Dashboard
     
    
        Chirps
     
 
				
			
				
					// resources/js/Layouts/AuthenticatedLayout.jsx
// for mobile
    
        Dashboard
     
    
        Chirps
     
 
				
			function store in controller
لقد تم تكوين النموذج الخاص بنا لنشر الرسائل على المسار chirps.store الذي أنشأناه سابقًا. فلنقم بتحديث طريقة store في فئة ChirpController الخاصة بنا للتحقق من صحة البيانات وإنشاء Chirp جديد لذلك نقوم باضافة الكود التالي
				
					//app/Http/Controllers/ChirpController.php
use Illuminate\Http\RedirectResponse;
public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'message' => 'required|string|max:255',
        ]);
 
        $request->user()->chirps()->create($validated);
 
        return redirect(route('chirps.index'));
    } 
				
			Creating a relationship
لعمل علاقة بين المستخدم والتغريدات نقوم باضافة الكود التالي في موديل Chirp
				
					//app/Models/Chirp.php
use Illuminate\Database\Eloquent\Relations\BelongsTo;
 protected $fillable = [
        'message',
    ];
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    } 
				
			function index in controller
لنقم بتحديث index لفئة ChirpController الخاصة بنا لتمرير التغريدات من كل مستخدم إلى صفحة الفهرس الخاصة بنا
				
					//app/Http/Controllers/ChirpController.php
 public function index(): Response
    {
        return Inertia::render('Chirps/Index', [
            'chirps' => Chirp::with('user:id,name')->latest()->get(),
        ]);
    } 
				
			update component
نقوم بانشاء مكون Chirp.jsx داخل components ليكون مسئول عن عرض التغريدات بشكل منفرد
				
					// resources/js/Components/Chirp.jsx
export default function Chirp({ chirp }) {
    return (
        
            
            
                
                    
                        {chirp.user.name}
                        {new Date(chirp.created_at).toLocaleString()}
                    
                
                {chirp.message}
            
        
    );
} 
				
			الان ، سنقوم بتحديث مكون الصفحة Chirps/Index الخاص بنا لقبول الخاصية chirps وعرض Chirps أسفل النموذج الخاص بنا باستخدام المكون الجديد
				
					// resources/js/Pages/Chirps/Index.jsx
import Chirp from '@/Components/Chirp';
//استبدال الكود التالي
export default function Index({ auth, chirps }) {
// اضافة الكود التالي بعد form
                    {chirps.map(chirp =>
                         
				
			- chirps.map: يمر عبر قائمة التغريدات ويعرض كل تغريدة باستخدام مكون- Chirp.
dayjs package
لو اردنا تنسيق التواريخ لتكون قابلة للقراءة بشكل افضل يمكننا أن نخطو خطوة أخرى إلى الأمام من خلال عرض التواريخ النسبية باستخدام مكتبة Day.js الشهيرة.
				
					npm install dayjs 
				
			بعد ذلك نقوم يتحديث صفحة chirp واضافة الاكواد التالية
				
					// resources/js/Components/Chirp.jsx
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
 
dayjs.extend(relativeTime);
// استبدال الكود التالي
{dayjs(chirp.created_at).fromNow()} 
				
			
				
					npm run build 
				
			Sharing to


 
								 
								 
								 
								 
								 
								 
								 
								




