بناء صفحة اتصل بنا احترافية في Laravel: دليل متكامل للمبتدئين والمحترفين

دقائق القراءة: 10

تُعد صفحة اتصل بنا عنصراً حيوياً في أي تطبيق ويب، فهي الجسر الذي يربط بين المستخدمين ومقدمي الخدمة أو أصحاب الموقع. مؤخراً، واجهت بعض التحديات أثناء محاولة إعداد هذه الصفحة في إطار عمل Laravel، لذا قررت مشاركة تجربتي لمساعدة أي شخص يطمح لتحقيق نفس الهدف.

Laravel هو إطار عمل PHP مفتوح المصدر يُستخدم لتطوير تطبيقات الويب، ويتبع نمط التصميم المعماري Model-View-Controller (MVC). يمتاز Laravel بمرونته وقدرته على تبسيط المهام المعقدة، بما في ذلك إعداد نماذج الاتصال وإدارة المراسلات.

المتطلبات الأساسية للبدء

قبل الغوص في تفاصيل التنفيذ، تأكد من توفر الأدوات والبرامج التالية على جهازك:

  • تثبيت Composer: مدير حزم PHP الأساسي.
  • إعداد خادم محلي: مثل XAMPP أو WAMP لتشغيل بيئة تطوير PHP.
  • محرر أكواد: مثل Sublime Text، VS Code، أو Atom.
  • تثبيت Git: لأغراض التحكم في الإصدارات وإدارة الشيفرة المصدرية.

الشروع في العمل: إعداد بيئة Laravel

بمجرد تثبيت Git، ستتمكن من الوصول إلى Git Bash (أو أي طرفية تفضلها)، والتي ستستخدمها لتشغيل الأوامر اللازمة لتثبيت Laravel وحزمه بسهولة.

تثبيت Laravel عبر Composer

بعد استيفاء جميع الشروط المذكورة أعلاه، سنستخدم الأمر التالي لتثبيت مثبت Laravel عالمياً:

composer global require laravel/installer

يتيح لنا الأمر أعلاه تنزيل مثبت Laravel باستخدام Composer الذي قمنا بتثبيته مسبقاً.

الآن، لإنشاء مشروع Laravel جديد، استخدم الأمر التالي:

laravel new project_name

تستغرق عملية التثبيت بعض الوقت، لذا تحلَّ بالصبر. لاحظ أن التثبيت سيتم في الدليل الذي تحدده في طرفية Bash الخاصة بك أو أي طرفية تختار استخدامها.

إنشاء هيكل المصادقة الأساسي

بعد تثبيت نسخة من تطبيق Laravel، يجب علينا إنشاء هيكل مصادقة أساسي، والذي يوفر صفحات تسجيل الدخول والتسجيل الجاهزة:

cd project_name
composer require laravel/ui
php artisan ui vue --auth

سيقوم الأمر الأخير بتثبيت عرض التخطيط (layout view)، وعرض التسجيل (registration view)، وعرض تسجيل الدخول (login view)، بالإضافة إلى المسارات (routes) لجميع عمليات مصادقة المستخدم.

إعداد متغيرات البيئة في ملف .env

الخطوة التالية هي إعداد متغيرات البيئة وإنشاء اتصال بقاعدة البيانات. في هذا المقال، سنستخدم عنوان IP وهمي مشترك لأغراض الشرح. افتح ملف .env في جذر مشروعك وقم بتحديث المتغيرات التالية:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=server_username
DB_PASSWORD=server_password

MAIL_DRIVER=smtp
MAIL_HOST=domain.com
MAIL_PORT=465
MAIL_USERNAME=noreply@domain.com
MAIL_PASSWORD=domain_password
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=noreply@domain.com
MAIL_FROM_NAME="${APP_NAME}"

لقد انتهينا الآن من إعداد اتصال قاعدة البيانات وإعدادات البريد الأساسية. في حالتي، أعمل مع XAMPP حيث يكون DB_USERNAME=root و DB_PASSWORD= فارغاً. لا تنسَ أيضاً تشغيل الخادم المحلي الخاص بك كما هو موضح أدناه.

صورة لخادم XAMPP قيد التشغيل

ترحيل قاعدة البيانات وبدء خادم التطوير

قبل تشغيل عمليات الترحيل (migrations) في Laravel، تحتاج إلى إنشاء اتصال بقاعدة البيانات. بما أننا حددنا your_database_name في تكوين .env أعلاه، يمكننا الآن إنشاء قاعدة بيانات فارغة باستخدام phpMyAdmin أو أداة إدارة قواعد البيانات المفضلة لديك.

إضافة اسم قاعدة بيانات جديدة في phpMyAdmin

في Git Bash، انتقل إلى دليل project_name وقم بتشغيل الأمر التالي:

cd project_name
php artisan migrate

سيؤدي هذا إلى تشغيل جميع عمليات ترحيل Laravel الافتراضية في تطبيقنا، طالما أنك أنشأت قاعدة بيانات مطابقة لـ DB_DATABASE الذي حددناه سابقاً.

يمكننا الآن بدء خادم التطوير الخاص بنا:

php artisan serve

شاشة طرفية تعرض بدء خادم تطوير Laravel

إنشاء ملف contact.blade.php

قم بإعداد صفحة الاتصال في مجلد resources > views بهذا الشكل (يمكنك وضعها في مجلد فرعي مثل template/client):

@extends('layouts.client.app')
@section('content')

Contact Us

@if (session('status'))
@endif
@endsection

تتضمن الشيفرة أعلاه امتداداً لملف تخطيط (layouts file) يحتوي على قسم الرأس (header section). كما تحتوي على عنوان القسم Contact Us بالإضافة إلى رسالة تُعرض للمستخدم إذا تم إرسال البريد بنجاح. التركيز الرئيسي هنا على قسم النموذج (form section) الذي ستراه في الشيفرة التالية:

تتضمن الشيفرة أعلاه حقول الإدخال المختلفة التي سنستخدمها لمعالجة معلومات المستخدم. تشمل الحقول: الاسم الكامل، عنوان البريد الإلكتروني، رقم الهاتف، الموضوع أو الغرض، الرسالة، تحميل الصورة (إن وجدت)، وأخيراً زر إرسال الرسالة لمعالجة إرسال النموذج. الآن سنقوم بدمج مقتطفي الشيفرة معاً لجعلها أكثر فائدة:

@extends('layouts.client.app')
@section('content')

Contact Us

@if (session('status'))
@endif
@endsection

الصورة أدناه هي تخطيط بسيط لما تبدو عليه صفحة الاتصال في الوقت الحالي:

شاشة تعرض صفحة اتصل بنا في تطبيق Laravel

إضافة المسارات (Routes) لتمكين طلبات GET و POST

أولاً، سنقوم بإعداد المسارات في ملف routes > web.php لعرض صفحة الاتصال عبر طلب GET وإرسال رسائل البريد عبر طلب POST (والذي تم تحديده في سمة action للنموذج أعلاه):

Route::get('/contact', 'HomeController@index')->name('contact');
Route::post('/contact', 'HomeController@send_mail')->name('addContact');

إضافة المنطق داخل HomeController

في مجلد app > Http > Controllers، قام هيكل Laravel بتوليد ملف HomeController.php. هذا الملف هو المكان الذي يكمن فيه منطق التطبيق. سنستخدم هذا المتحكم (Controller) الافتراضي وننشئ دالة باسم index(). سنستخدمها لعرض صفحة اتصل بنا في كل مرة يزور فيها المستخدم المسار أو عنوان URL في التطبيق.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller
{
    public function index()
    {
        return view('template.client.contact'); //renders the contact page
    }
}

في نفس HomeController، نحتاج إلى إنشاء دالة أخرى باسم send_mail(). ستقوم هذه الدالة بالتحقق من صحة جميع مدخلات المستخدم والتأكد من أن الحقول ليست فارغة وأن البيانات الصحيحة قد تم تحليلها. بعد ذلك، سنقوم بإنشاء متغير يسمى $contact لتخزين قيم مصفوفة جميع بيانات المستخدم، بما في ذلك تحميلات الصور. يأتي Laravel مزوداً بنظام ملفات (filesystem) يتيح لنا التعامل مع الصور بسهولة. يتم توفير الدالتين Mail::to(...) و send() من خلال Illuminate\Support\Facades\Mail التي قمنا بتضمينها في أعلى الشيفرة. لقد قمنا أيضاً بتضمين Mailable، والذي سأشرحه قريباً. نحتاج الآن إلى تنبيه المستخدمين عند إرسال الرسالة وإعادة توجيههم.

<?php

use Illuminate\Support\Facades\Mail;
use App\Mail\ContactFormMail;

class HomeController extends Controller
{
    public function send_mail(Request $request)
    {
        $this->validate($request, [
            'fullname' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255'],
            'phone_number' => ['string', 'max:255'],
            'subject' => ['required', 'string', 'max:255'],
            'message' => ['required', 'string', 'max:255']
        ]);

        $contact = [
            'fullname' => $request['fullname'],
            'email' => $request['email'],
            'phone_number' => $request['phone_number'],
            'subject' => $request['subject'],
            'message' => $request['message'],
            'screenshot' => $request->file('screenshot')->store('contact', 'public')
        ];

        Mail::to('receipent@domain.com')->send(new ContactFormMail($contact));

        return redirect()->route('contact')->with('status', 'Your Mail has been received');
    }
}

بدمج كلتا الدالتين أعلاه، سيبدو ملف HomeController.php الخاص بك كما يلي:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Mail\ContactFormMail;

class HomeController extends Controller
{
    public function index()
    {
        return view('template.client.contact'); //renders the contact page
    }

    public function send_mail(Request $request)
    {
        $this->validate($request, [
            'fullname' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255'],
            'phone_number' => ['string', 'max:255'],
            'subject' => ['required', 'string', 'max:255'],
            'message' => ['required', 'string', 'max:255']
        ]);

        $contact = [
            'fullname' => $request['fullname'],
            'email' => $request['email'],
            'phone_number' => $request['phone_number'],
            'subject' => $request['subject'],
            'message' => $request['message'],
            'screenshot' => $request->file('screenshot')->store('contact', 'public')
        ];

        Mail::to('receipent@domain.com')->send(new ContactFormMail($contact));

        return redirect()->route('contact')->with('status', ' Your Mail has been received');
    }
}

بعد دمج كلتا الدالتين المذكورتين أعلاه، نكون قد انتهينا من المنطق الخاص بـ HomeController. الآن دعنا ننتقل إلى الخطوة التالية.

توليد Laravel Mailable

كل بريد يتم إرساله داخل تطبيق Laravel يمثله "mailable". دعنا ننشئ mailable بصيغة markdown لمعلومات الاتصال التي نريد معالجتها:

php artisan make:mail ContactFormMail --markdown=template.client.contactform

سيقوم الأمر أعلاه بإنشاء ملف markdown في دليل resources > views > template > client، وسيقوم أيضاً بإنشاء ملف mailable في app > Mail > ContactFormMail.php.

إعداد ContactFormMail.php (بدون مرفقات)

في ملف ContactFormMail.php، لدينا مقتطف الشيفرة التالي الذي يتيح لنا إرسال رسائل بريد إلكتروني بدون مرفقات:

<?php

namespace App\Mail;

use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class ContactFormMail extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this->user = $data;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->from('noreply@domain.com')
            ->markdown('template.client.contactform')
            ->with([
                'subject' => $this->user['subject'],
                'message' => $this->user['message'],
                'email' => $this->user['email'],
                'phone_number' => $this->user['phone_number'],
                'fullname' => $this->user['fullname'],
            ]);
    }
}

دعنا نحلل هذه الشيفرة قليلاً:

  • في الدالة البانية __construct()، نقوم بتحليل جميع بيانات المستخدم كمعامل وإعادة تعيينها لخاصية $this->user.
  • في الدالة build()، يتم تكوين جميع إعدادات فئة mailable.
  • تحدد الدالة from() مرسل البريد الإلكتروني (في حالتي noreply@domain.com).
  • تتيح لك الدالة with() تخصيص كيفية عرض رسائل البريد الإلكتروني في قالب markdown الذي تم إنشاؤه. في هذا المقال، سنقوم بتعيين جميع الحقول كأزواج مفتاح-قيمة داخل المصفوفة بحيث يمكننا داخل قالب markdown الوصول إلى كل قيمة بمفتاحها الفريد.
  • تقبل الدالة markdown() اسم قالب markdown المراد عرضه مع معامل بيانات اختياري (إذا لم نكن نستخدم الدالة with()).
  • أخيراً، تحدد الدالة to() المستلم للبريد. في HomeController أعلاه، قم بتغيير 'receipent@domain.com' إلى عنوان المستلم الفعلي.

إضافة البيانات إلى ملف Markdown

الآن نحتاج إلى تكوين ملف markdown في دليل resources > views > template > client. بما أن لدينا أزواج مفتاح-قيمة جاهزة، فمن الأسهل الإشارة إليها بالمفاتيح في ملف markdown كما هو موضح أدناه:

@component('mail::message')
# {{$subject}}
## {{$message}}

Feel free to contact me via {{$phone_number}} or {{$email}}

Thanks,
{{$fullname}} {{ config('app.name') }} @endcomponent

في هذه المرحلة، نكون قد أوشكنا على الانتهاء من إرسال بريد إلكتروني بدون مرفقات. تهانينا على متابعة العملية حتى الآن! الآن دعنا ننتقل إلى كيفية إرسال بريد إلكتروني مع مرفق.

إرسال رسائل البريد الإلكتروني مع مرفقات

يأتي Laravel مزوداً بنظام ملفات قوي، لذا فإن إرسال رسائل البريد الإلكتروني مع مرفقات ليس صعباً للغاية. سنستفيد من هذه الميزة وننشئ مساحة تخزين للمستخدمين حيث سنقوم بتخزين ملفاتهم المرفقة داخل التطبيق.

أولاً، قم بإنشاء رابط رمزي (symbolic link) لمجلد التخزين العام باستخدام الأمر التالي:

php artisan storage:link

ملاحظة هامة: في HomeController أعلاه، لقد حددت بالفعل دليلاً للتخزين للملفات التي يتم تحميلها ('contact'). يجب عليك فعل الشيء نفسه عن طريق إنشاء مجلد (يسمى contact) داخل storage > app > public > contact. أيضاً، في ملف config > filesystems.php، تحقق وتأكد من أن قرص نظام الملفات الافتراضي مضبوط على return ['default' => 'public'].

الآن، سيبدو ملف ContactFormMail.php الخاص بنا بهذا الشكل. أصبحنا الآن قادرين على استخدام الدالة attachFromStorage() التي تشير إلى مسار الملف المخزن:

<?php

namespace App\Mail;

use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class ContactFormMail extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public $user;

    public function __construct($data)
    {
        $this->user = $data;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->from('noreply@domain.com')
            ->markdown('template.client.contactform')
            ->attachFromStorage(
                $this->user['screenshot']
            )
            ->with([
                'subject' => $this->user['subject'],
                'message' => $this->user['message'],
                'email' => $this->user['email'],
                'phone_number' => $this->user['phone_number'],
                'fullname' => $this->user['fullname']
            ]);
    }
}

الإضافة الوحيدة هنا هي الدالة attachFromStorage(). تُستخدم هذه الدالة لمعالجة الملفات المرفقة (سواء كانت صورة أو PDF) أثناء عملية إرسال البريد بأكملها. في ملف markdown الذي استخدمناه سابقاً، يمكننا إعادة صياغته قليلاً ليبدو كما هو موضح أدناه:

<div class="row">
    <h1 class="text-dark">{{$subject}}</h1>
    <h3>{{$message}}</h3>
    <h4>You can reach me via mail or telephone : {{$email}} or {{$phone_number}} <br/>
        Thanks
    </h4>
</div>

لقد نجحنا الآن في إعداد صفحة الاتصال مع دعم المرفقات! الصورة أدناه توضح رسالة بريد إلكتروني تم إرسالها بنجاح مع مرفق.

لقطة شاشة لرسالة بريد إلكتروني تم إرسالها بنجاح مع مرفق

الخلاصة التقنية

يوضح هذا الدليل الشامل قوة ومرونة إطار عمل Laravel في بناء ميزات أساسية مثل صفحة اتصل بنا. من خلال الاستفادة من مكوناته المدمجة مثل نظام المسارات (Routing)، المتحكمات (Controllers)، عروض Blade، ونظام البريد (Mailable)، يمكن للمطورين إنشاء حلول قوية وفعالة بأقل جهد. إن القدرة على التعامل مع المرفقات بسلاسة عبر نظام الملفات المدمج في Laravel تضيف قيمة كبيرة، مما يجعله خياراً ممتازاً لتطبيقات الويب الحديثة التي تتطلب تفاعلاً غنياً مع المستخدم. يُنصح دائماً بمراجعة الوثائق الرسمية لـ Laravel للتعمق أكثر في الميزات المتقدمة وأفضل الممارسات.

اترك تعليقاً

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