laravel with react js

react js and laravel 11 for chirps

دمج 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) هو برنامج تحرير النصوص بيئة تطوير مفتوحة المصدر وخفيفة الوزن تم تطويرها بواسطة مايكروسوفت. تعتبر أحد أشهر وأكثر الأدوات شعبية بين المطورين لتطوير البرمجيات وتحرير النصوص بفضل ميزاتها القوية والمرونة التي توفرها.

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 إلى وحدة التحكم، ولكن ستتم إعادة كتابة الكود لاحقًا 

				
					<?php

namespace App\Http\Controllers;
 
use App\Models\Chirp;
use Illuminate\Http\Request; 
use Illuminate\Http\Response; 
 
class ChirpController extends Controller
{
    public function index(): Response 
    {
        return response('Hello, World!');
    }
}

				
			

Routing التوجيه

سوف نقوم بتحديث ملف web.php داخل routes باضافة الاكواد التالية:

				
					use App\Http\Controllers\ChirpController;

Route::resource('chirps', ChirpController::class)
    ->only(['index', 'store'])
    ->middleware(['auth', 'verified']);
				
			

Inertia

Inertia.js هي مكتبة تتيح للمطورين إنشاء تطبيقات الواجهة الأمامية باستخدام Vue.js، React.js، أو Svelte، مع الاحتفاظ بإطار العمل الخلفي مثل Laravel لتوفير تجربة تطوير سلسة ومتكاملةو سهولة الدمج بين الامامية والخلفية
نقوم بتحديث ملف كونترولر ChirpController.php ليصبح بالشكل الاتي بعد اضافة 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 user={auth.user}>
            <Head title="Chirps" />

				
			
  • AuthenticatedLayout: يغلف المكون الرئيسي ويوفر تخطيطًا للمستخدم المصادق عليه.
  • Head: يحدد عنوان الصفحة.
				
					            <div className="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8">
                <form onSubmit={submit}>
                    <textarea
                        value={data.message}
                        placeholder="What's on your mind?"
                        className="block w-full border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm"
                        onChange={e => setData('message', e.target.value)}
                    ></textarea>
                    <InputError message={errors.message} className="mt-2" />
                    <PrimaryButton className="mt-4" disabled={processing}>Chirp</PrimaryButton>
                </form>   
            </div>
        </AuthenticatedLayout>
    );
}

				
			
  • 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

<div className="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
    <NavLink href={route('dashboard')} active={route().current('dashboard')}>
        Dashboard
    </NavLink>
    <NavLink href={route('chirps.index')} active={route().current('chirps.index')}>
        Chirps
    </NavLink>
</div>
				
			
				
					// resources/js/Layouts/AuthenticatedLayout.jsx
// for mobile

<div className="pt-2 pb-3 space-y-1">
    <ResponsiveNavLink href={route('dashboard')} active={route().current('dashboard')}>
        Dashboard
    </ResponsiveNavLink>
    <ResponsiveNavLink href={route('chirps.index')} active={route().current('chirps.index')}>
        Chirps
    </ResponsiveNavLink>
</div>
				
			

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 (
        <div className="p-6 flex space-x-2">
            <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-gray-600 -scale-x-100" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
                <path strokeLinecap="round" strokeLinejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
            </svg>
            <div className="flex-1">
                <div className="flex justify-between items-center">
                    <div>
                        <span className="text-gray-800">{chirp.user.name}</span>
                        <small className="ml-2 text-sm text-gray-600">{new Date(chirp.created_at).toLocaleString()}</small>
                    </div>
                </div>
                <p className="mt-4 text-lg text-gray-900">{chirp.message}</p>
            </div>
        </div>
    );
}
				
			

الان ، سنقوم بتحديث مكون الصفحة Chirps/Index الخاص بنا لقبول الخاصية chirps وعرض Chirps أسفل النموذج الخاص بنا باستخدام المكون الجديد

				
					// resources/js/Pages/Chirps/Index.jsx

import Chirp from '@/Components/Chirp';
//استبدال الكود التالي
export default function Index({ auth, chirps }) {

// اضافة الكود التالي بعد form
<div className="mt-6 bg-white shadow-sm rounded-lg divide-y">
                    {chirps.map(chirp =>
                        <Chirp key={chirp.id} chirp={chirp} />
                    )}
                </div>
				
			
  • 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);

// استبدال الكود التالي
<small className="ml-2 text-sm text-gray-600">{dayjs(chirp.created_at).fromNow()}</small>
				
			
				
					npm run build
				
			
chirps - comment
result

Sharing to

Facebook
Twitter
LinkedIn

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top