اكتشف إطار PHP Laravel


الدرس: العلاقة 1:n


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

المعطيات


الترحيل
سوف نستمر في استخدام الجدول   users الذي رأيناه في الفصول السابقة. سنقوم بإنشاء جدول جديد   posts يهدف إلى حفظ المقالات. إذا قمت بالفعل بإنشاء الجدول   users مع حذف السجلات لهذا الجدول ، فسنقوم بإعادة إنشائه.
لقد حددنا بالفعل ترحيل الجدول   users ويجب أن يكون لديك الملف في المجلد   database/migrations . أذكرك بالكود:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration {

    public function up()
    {
        Schema::create('users', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('name')->unique();
            $table->string('email')->unique();
            $table->string('password', 60);
            $table->boolean('admin')->default(false);
            $table->rememberToken();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::drop('users');
    }

}
سننشئ أيضًا ترحيلًا للجدول posts :

php artisan make:migration create_posts_table
وسنقوم بإكمال الكود كما يلي:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration {

    public function up()
    {
        Schema::create('posts', function(Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
            $table->string('titre', 80);
            $table->text('contenu');
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')
                  ->references('id')
                  ->on('users')
                  ->onDelete('restrict')
                  ->onUpdate('restrict');
        });
    }

    public function down()
    {
        Schema::table('posts', function(Blueprint $table) {
            $table->dropForeign('posts_user_id_foreign');
        });
        Schema::drop('posts');
    }

}
عادة يجب أن يكون لديك هذه الترحيلات 3:
framework Laravel MVC
3 ترحيلات قم الترحيل:

php artisan migrate
يجب أن ينتهي بك الأمر إلى الجداول الثلاثة الموجودة في القاعدة بالإضافة إلى الجدول migrations :
framework Laravel MVC
الجداول 4
من أجل المستخدمين ، علينا أن نبدأ في ترحيل جديد للجدول    users . في الواقع نحن بحاجة إلى أن يبدأ مفتاح الجدول في 1.
مجموع المستخدمين
سنرى الآن كيفية ملء جداولنا بالسجلات لإجراء اختباراتنا. سنقوم بإنشاء ملفين في المجلد لهذا   database/seeds . عادة يجب أن يكون لديك بالفعل ملف في هذا المجلد   DatabaseSeeder.php  : 
framework Laravel MVC
ملف DatabaseSeeder
مع هذا الكود:

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return  void
     */
    public function run()
    {
        // $this->call(UserTableSeeder::class);
    }
}
الغرض من هذه الطريقة Run هو تنفيذ الملفات الخاصة مجموع المستخدمين. لديك بالفعل خط الإطلاق المعلق للجدول users . لذلك سنقوم بإلغاء التعليق عليه ونضيف الكود لجدول المنشورات:

<?php
public function run()
{
    $this->call(UserTableSeeder::class);
    $this->call(PostTableSeeder::class);
}
ضع الاسطر في هذا الترتيب ، وسوف تفهم قريبًا سبب الضرورة.
ثم سنقوم بإنشاء الملف   UserTableSeeder.php لمجموع المستخدمين في الجدول   users  :

<?php

use Illuminate\Database\Seeder;

class UserTableSeeder extends Seeder {

    public function run()
    {
        DB::table('users')->delete();

        for($i = 0; $i < 10; ++$i)
        {
            DB::table('users')->insert([
                'name' => 'Nom' . $i,
                'email' => 'email' . $i . '@blop.fr',
                'password' => bcrypt('password' . $i),
                'admin' => rand(0, 1)
            ]);
        }
    }
}
وبالتالي سنقوم بإنشاء 10 مستخدمين.
نوفر أيضًا الملف   PostTableSeeder.php بهذا الكود:

<?php

use Illuminate\Database\Seeder;
use Carbon\Carbon;

class PostTableSeeder extends Seeder {

    private function randDate()
    {
        return Carbon::createFromDate(null, rand(1, 12), rand(1, 28));
    }

    public function run()
    {
        DB::table('posts')->delete();

        for($i = 0; $i < 100; ++$i)
        {
            $date = $this->randDate();
            DB::table('posts')->insert([
                'titre' => 'Titre' . $i,
                'contenu' => 'Contenu' . $i . ' Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
                'user_id' => rand(1, 10),
                'created_at' => $date,
                'updated_at' => $date
            ]);
        }
    }
}
وبالتالي ، سننشئ 100 مقال عشوائيًا للمستخدمين العشرة. سنرى قريبا كيف يتم الاتصال بين الاثنين.
الفئةCarbon ، من الحزمة المحملة بواسطة Laravel ، تسمح بمعالجة التواريخ بسهولة. لا تتردد في استخدامه بمجرد وجود تواريخ للإدارة.
يجب أن يكون لديك الآن هذه الملفات في مجلد مجموع المستخدمين:
framework Laravel MVC
ملفات مجموع المستخدمين
الآن فقط استخدم الأمر Artisan لإطلاق مجموع المستخدمين:

php artisan db:seed
عادة يجب أن يكون لديك كلا الجدولين ممتلئين في نهاية هذا الطلب.
إذا كانت لديك رسالة تخبرك أنه userTableSeeder لم يتم العثور على الفئة   أو الفئة الأخرى ، فأصدر الأمر  "composer dumpautoload" ، ثم أعد تشغيل المجموعة.
يجب الآن ملء الجداول ، على سبيل المثال للمستخدمين:
framework Laravel MVC
جدول المستخدمين

العلاقة


لدينا الموقف التالي:
  • يمكن للمستخدم كتابة مقالات متعددة ،
  •  مقال كتبه مستخدم واحد.
يجب أن نجد طريقة للإشارة إلى هذه العلاقة في الجداول. المبدأ بسيط: يتم توفير سطر في الجدول posts يهدف إلى تلقي معرف المستخدم الذي يكتب المقالة. نسمي هذا السطر مفتاحًا خارجيًا لأننا نقوم بحفظ المفتاح من جدول آخر هنا. هنا تمثيل مرئي لهذه العلاقة:
framework Laravel MVC
المفتاح الخارجي
تشاهد العلاقة المرسومة بين المفتاح   id في الجدول   users والمفتاح الخارجي   user_id في الجدول   posts . تهدف عملية الترحيل التي أنشأناها أعلاه إلى إعلام أساس هذه العلاقة. انظر إلى هذا الكود:

<?php
$table->foreign('user_id')
      ->references('id')
      ->on('users')
      ->onDelete('restrict')
      ->onUpdate('restrict');
في الجدول ، نعلن عن مفتاح خارجي ( foreign) يُسمى   user_id أي من المراجع ( references) السطر   id في الجدول ( on)    users . في حالة الحذف ( onDelete) أو التعديل ( onUpdate) هناك قيود ( restrict) . ماذا يعني هذان الشرطان الأخيران؟
تخيل أن لديك مستخدم له معرف 5 وله مقالتان ، لذلك في الجدول   posts لدينا سجلان لهما    user_id  بالقيمة 5. إذا حذفنا المستخدم ماذا سيحدث؟ نخاطر في النهاية بسجلينا في الجدول   posts باستخدام مفتاح خارجي لا يتوافق مع أي سجل في الجدول   users . من خلال تحديد "تقييد restrict " ، نمنع حذف مستخدم لديه مقالات. لذلك يجب أن نبدأ بحذف مقالاته قبل حذفه هو. يقال أن القاعدة تضمن التكامل المرجعي. ولن يقبل أننا نستخدم  user_id لقيمة غير موجودة في الجدول    users .
الاحتمال الآخر هو "تتالي cascade " بدلاً من "تقييد restrict " . في هذه الحالة ، إذا قمت بحذف مستخدم ، فسوف يتسلسل مقالات هذا المستخدم. إنه خيار نادرًا ما يستخدم لأنه قد يكون خطيرًا ، خاصةً في قاعدة بيانات ذات جداول متعددة في. لكنها أيضًا استراتيجية فعالة للغاية لأنها محرك قاعدة البيانات المسؤول عن إدارة السجلات ذات الصلة ، لذلك لا داعي للقلق بشأن الكود.
لم نتمكن أيضًا من الإشارة إلى أن هناك علاقة ونديرها فقط في التعليمات البرمجية الخاصة بنا. لكن الأمر أكثر خطورة لأن أدنى خطأ في إدارة السجلات في الكود الخاص بك ينطوي على مخاطر حدوث عواقب وخيمة في قاعدة البيانات الخاصة بك مع عدم تناسق متعددة.

المُجسمات


لدينا بالفعل مُجسم   User  ( app/User.php) . سيتعين علينا فقط إضافة طريقة للعثور بسهولة على مقالات المستخدم. أضف هذا الكود في القالب   User  :

<?php
public function posts() 
{
    return $this->hasMany('App\Post');
}
نعلن هنا أن المستخدم لديه عدة  hasMany مقالات ( posts) . سيوفر ذلك طريقة عملية لاسترداد المقالات من المستخدم.
كن حذرا مع مساحات الأسماء!
نحتاج أيضًا إلى مُجسم posts :

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{

    protected $fillable = ['titre','contenu','user_id'];

    public function user() 
    {
        return $this->belongsTo('App\User');
    }

}
لدينا هنا الطريقة   user (في صيغة المفرد) التي تتيح لنا العثور على المستخدم الذي تنتمي إليه (belongsTo)المقالة . لذلك هو عكس الأسلوب السابق.
فيما يلي رسم تخطيطي لهذه العلاقة مع طريقتين:
framework Laravel MVC
طريقتين العلاقة
أذكرك بأنه إذا لم تحدد اسم الجدول في نموذج بشكل صريح ، فإن Laravel يستنتجه من اسم المُجسم بوضعه في صيغة الجمع (باللغة الإنجليزية) وبوضع الحرف الأول في أحرف صغيرة.
تجعل الطريقتان المطبقتان من السهل استرداد سجل مرتبط. على سبيل المثال الحصول على جميع مقالات المستخدم الذي لديه المعرف 1:

<?php
$articles = App\User::find(1)->posts;
بنفس الطريقة يمكننا أن نجد المستخدم الذي كتب المقالة ذات المعرف 1:

<?php
$user = App\Post::find(1)->user;
يمكنك أن ترى أن الكود يصبح واضحًا جدًا مع هذه الطرق  .
يحتوي Laravel على أداة tinker التي تتيح لك إدخال الأوامر في وحدة التحكم وبالتالي التفاعل مباشرة مع التطبيق. يجب أن تبدأ الأمر php artisan tinker . يمكننا بعد ذلك استخدامه مباشرة:

php artisan tinker
Psy Shell v0.6.1 (PHP 5.5.12 ÔÇö cli) by Justin Hileman
>>> App\User::find(1)->posts
=> Illuminate\Database\Eloquent\Collection {#661
 all: [
 App\Post {#662
 id: 47,
 created_at: "2015-03-19 12:39:12",
 updated_at: "2015-03-19 12:39:12",
 titre: "Titre46",
 contenu: "Contenu46 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
 user_id: 1,
 },
...

وحدة التحكم والطرق


h5> وحدة التحكم
الآن بعد أن أصبح كل شيء في مكانه على مستوى البيانات ، دعونا نلقي نظرة على إدارة كل هذا. سنقوم بإنشاء وحدة تحكم للعناصر التي سوف نسميها   PostController . سيكون على وحدة التحكم هذه إدارة عدة أشياء:
  • تلقي الطلب لعرض مقالات المدونة والاستجابة المكيفة ،
  • تلقي طلب النموذج لإنشاء مقال جديد وإرساله ،
  • استلام نموذج تقديم مقال جديد (محجوز للمستخدم الذي قام بتسجيل الدخول) وتسجيله ،
  • استلام طلب حذف مقال (محجوز للمسؤول) وحذفه.
للتبسيط ، لن نوفر إمكانية تعديل المقال. 
ساستخدم وحدة تحكم الموارد. هنا هو الكود:

<?php

namespace App\Http\Controllers;

use App\Repositories\PostRepository;
use App\Http\Requests\PostRequest;

class PostController extends Controller
{

    protected $postRepository;

    protected $nbrPerPage = 4;

    public function __construct(PostRepository $postRepository)
    {
        $this->middleware('auth', ['except' => 'index']);
        $this->middleware('admin', ['only' => 'destroy']);

        $this->postRepository = $postRepository;
    }

    public function index()
    {
        $posts = $this->postRepository->getPaginate($this->nbrPerPage);
        $links = $posts->render();

        return view('posts.liste', compact('posts', 'links'));
    }

    public function create()
    {
        return view('posts.add');
    }

    public function store(PostRequest $request)
    {
        $inputs = array_merge($request->all(), ['user_id' => $request->user()->id]);

        $this->postRepository->store($inputs);

        return redirect(route('post.index'));
    }

    public function destroy($id)
    {
        $this->postRepository->destroy($id);

        return redirect()->back();
    }

}
كالعادة ، أنا سأحقن طلب النموذج والمستودع.
لاحظ استخدام الوسيطة لتصفية المستخدمين ، وسوف نرى ذلك بعد من ذلك بقليل.
الطرق
رأينا في الفصل المتعلق بالموارد كيفية إنشاء طرق لهذا النوع من وحدة التحكم. سيتعين علينا فقط الإشارة إلى أننا لا نريد استخدام الطرق السبعة المتاحة ولكن فقط بعض الطرق:

<?php
Route::resource('post', 'PostController', ['except' => ['show', 'edit', 'update']]);
مع except الإشارة إلى أنني لا أريد مسارًا للطرق الثلاثة المذكورة. إليك ما يشبه استخدام Artisan لتصور الطرق ( php artisan route:list) :
framework Laravel MVC framework Laravel MVC
الطرق
المستودع
بالنسبة للإدارة ، سنضع الملفات في المجلد app/Repositories كما فعلنا بالفعل لإدارة المستخدم:
framework Laravel MVC
مستودع
مع هذا الكود:

<?php

namespace App\Repositories;

use App\Post;

class PostRepository
{

    protected $post;

    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    public function getPaginate($n)
    {
        return $this->post->with('user')
        ->orderBy('posts.created_at', 'desc')
        ->paginate($n);
    }

    public function store($inputs)
    {
        $this->post->create($inputs);
    }

    public function destroy($id)
    {
        $this->post->findOrFail($id)->delete();
    }

}
سنرى أدناه فائدة كل هذه الطرق.

الوسيطة


لقد رأينا أنه في وحدة التحكم نطبق اثنين من البرامج الوسيطة:
  • auth (المصادقة)  : الوصول محجوز للمستخدمين المصادق عليهم بصرف النظر عن طريقة   index عرض المدونة ،
  • admin  (المسؤول)  : الوصول محفوظة للمسؤولين لهذه الطريقة   destroy .
تم التخطيط للوسيطة الأولى بالفعل في Laravel ، من ناحية أخرى ، الثانية غير موجودة. لذلك عليك إنشائها.
مرة أخرى سوف نستخدم Artisan:

php artisan make:middleware Admin
نجد الملف مرتبًا:
framework Laravel MVC
الوسيطة للإدارة
نحصل على هذا الكود:

<?php

namespace App\Http\Middleware;

use Closure;

class Admin
{

    /**
     * Handle an incoming request.
     *
     * @param    \Illuminate\Http\Request  $request
     * @param    \Closure  $next
     * @return  mixed
     */
    public function handle($request, Closure $next)
    {
        //
    }

}
يتعين علينا كتابة الكود الخاص بنا ، والذي يعطي:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\RedirectResponse;

class Admin
{

    /**
     * Handle an incoming request.
     *
     * @param    \Illuminate\Http\Request  $request
     * @param    \Closure  $next
     * @return  mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->user()->admin)
        {
            return $next($request);
        }
        return new RedirectResponse(url('post'));
    }

}
إذا لم يكن المستخدم مسؤولًا ، فنحن نعيد التوجيه إلى عرض المدونة. لاحظ أننا لا نتحقق في هذا المستوى من أن لدينا مستخدمًا معتمدًا لأنه في مُنشئ وحدة التحكم ، يتم وضع مرشح المصادقة قبل عامل تصفية المسؤول. إذا كان الأمر عكس ذلك ، فمن الواضح أننا سنواجه خطأً عند محاولة الوصول إلى عنوان url لحذف مقال.
لقد أنشأنا الوسيطة Created ولكن هذا لا يكفي ، نحتاج الآن إلى رابط بين الاسم الذي نريد أن نعطيه للمرشح والفئة التي أنشأناها للتو. ابحث في الملف عن   app/Http/Kernel.php  سطور التعليمات البرمجية هذه:

<?php
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
ستجد هنا جميع البرامج الوسيطة المُعلن عنها ، ما عليك سوى إضافة الأداة الجديدة:

<?php
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'admin' => \App\Http\Middleware\Admin::class,
];

التحقق من صحة


الآن دعونا نرى التحقق من الصحة. لا تزال بحاجة إلى إنشاء طلب نموذج:

php artisan make:request PostRequest
يتم وضعها في المجلد:
framework Laravel MVC

<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class PostRequest extends Request
{

    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'titre' => 'required|max:80',
            'contenu' => 'required'
        ];
    }

}

كيفية العمل


h5> قائمة المقالات
يتم الحصول على قائمة المقالات باستخدام عنوان url (الفعل get ) : 

.../post
من يصل إلى طريقة التحكم index :

<?php
public function index()
{
    $posts = $this->postRepository->getPaginate($this->nbrPerPage);
    $links = $posts->render();

    return view('posts.liste', compact('posts', 'links'));
}
نرسل هنا عدد المقالات في الصفحة (الموضوعة في الخاصية $nbrPerPage ) إلى طريقة التخزين getPaginate :

<?php
public function getPaginate($n)
{
    return $this->post->with('user')
    ->orderBy('posts.created_at', 'desc')
    ->paginate($n);
}
نريد المقالات التي تحتوي على ( with) المستخدم ( user) ، بترتيب تواريخ الإنشاء ( posts.created_at) تنازليًا ( desc) مع ترقيم الصفحات من المقالات ( $n) .
هناك طريقة latest ( و oldest للعكس) الذي يبسط بناء الجملة:

<?php
return $this->post->with('user')
->latest('posts.created_at')
->paginate($n);
h5> إضافة مقال
يتم طلب نموذج إنشاء المقالة باستخدام عنوان url (الفعل    get ) :

.../post/create
وحدة التحكم بإرجاع العرض مباشرة:

<?php
public function create()
{
    return view('posts.add');
}
تتم إعادة النموذج باستخدام عنوان url (الفعل post ) :

.../post
نصل إلى طريقة التحكم store :

<?php
public function store(PostRequest $request)
{
    $inputs = array_merge($request->all(), ['user_id' => $request->user()->id]);

    $this->postRepository->store($inputs);

    return redirect(route('post.index'));
}
نحن نحقن طلب النموذج ، وأنا لا أصر عليه لأنه لا يوجد شيء جديد في هذا المستوى. نحصل على إدخالات النموذج للعنوان والمحتوى. بالنسبة لمعرف المستخدم ، نحن نعلم أنه متصل بالضرورة لذلك نحن نسترجع هذا المعرف مع الطلب. إذا سارت عملية التحقق بشكل صحيح store ، فسنرسل إلى طريقة المستودع:

<?php
public function store($inputs)
{
    $this->post->create($inputs);
}
h5> حذف مقال
أخيرًا ، نحذف مقالًا بعنوان url (فعل    delete ) :

.../post/id
حيث id يمثل معرف المقالة المراد حذفها. هذه طريقة التحكم destroy :

<?php
public function destroy($id)
{
    $this->postRepository->destroy($id);

    return redirect()->back();
}
من يرسل إلى طريقة destroy مستودع التخزين:

<?php
public function destroy($id)
{
    $this->post->findOrFail($id)->delete();
}
هنا نقوم بحذف المقالة مع طريقة    النموذج delete  .

العرض


الآن دعونا نرى العرض. سنقوم بتعديل نموذجنا ( resources/views/template.blade.php ) قليلاً :

<!DOCTYPE html>
<html lang="fr">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Mon joli site</title>
        {!! Html::style('https://netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css') !!}
        {!! Html::style('https://netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css') !!}
        <!--[if lt IE 9]>
            { { Html::style('https://oss.maxcdn.com/libs/html5shiv/3.7.2/html5shiv.js') }}
            { { Html::style('https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js') }}
        <![endif]-->
        <style> textarea { resize: none; } </style>
    </head>
  <body>
    <header class="jumbotron">
      <div class="container">
        <h1 class="page-header">{!! link_to_route('post.index', 'Mon joli blog') !!}</h1>
        @yield('header')
      </div>
    </header>
    <div class="container">
      @yield('contenu')
    </div>
  </body>
</html>
نحتاج إلى عرض لعرض مشاركات المدونة وبعض الأزرار للإدارة ( resources/views/posts/liste.blade.php) :

@extends('template')

@section('header')
    @if(Auth::check())
        <div class="btn-group pull-right">
            {!! link_to_route('post.create', 'Créer un article', [], ['class' => 'btn btn-info']) !!}
            {!! link_to('logout', 'Deconnexion', ['class' => 'btn btn-warning']) !!}
        </div>
    @else
        {!! link_to('login', 'Se connecter', ['class' => 'btn btn-info pull-right']) !!}
    @endif
@endsection

@section('contenu')
    @if(isset($info))
        <div class="row alert alert-info">{ { $info }}</div>
    @endif
    {!! $links !!}
    @foreach($posts as $post)
        <article class="row bg-primary">
            <div class="col-md-12">
                <header>
                    <h1>{ { $post->titre }}</h1>
                </header>
                <hr>
                <section>
                    <p>{ { $post->contenu }}</p>
                    @if(Auth::check() and Auth::user()->admin)
                        {!! Form::open(['method' => 'DELETE', 'route' => ['post.destroy', $post->id]]) !!}
                            {!! Form::submit('Supprimer cet article', ['class' => 'btn btn-danger btn-xs ', 'onclick' => 'return confirm(\'Vraiment supprimer cet article ?\')']) !!}
                        {!! Form::close() !!}
                    @endif
                    <em class="pull-right">
                        <span class="glyphicon glyphicon-pencil"></span> { { $post->user->name }} le {!! $post->created_at->format('d-m-Y') !!}
                    </em>
                </section>
            </div>
        </article>
        <br>
    @endforeach
    {!! $links !!}
@endsection
مع هذا الجانب لمستخدم غير متصل:
framework Laravel MVC
جانب من Blog
يرسل زر "Connect" إلى عنوان url :

.../login
وهو ما يتوافق مع ما رأيناه في الفصل السابق وينبغي أن يؤدي إلى نموذج تسجيل الدخول إذا كان لديك كل شيء في مكانه كما خططنا مسبقًا:
framework Laravel MVC
نموذج تسجيل الدخول
للسجل ، أنا هنا أقوم باستخدام عرض تلقائي لـ Laravel . الأمر متروك لك ، بالطبع ، لتتمكن من كتابة هذا العرض أو حتى من الأفضل تكييفه مع لغة المستخدم (سنرى هذا الجانب في فصل لاحق).
لكي يعمل التطبيق الخاص بك بشكل جيد مع وحدة التحكم ،   AuthController  يجب عليك تعديل الخاصية   redirectTo في وحدة التحكم هذه:

<?php
protected $redirectTo = 'post';
لذلك سيتم إعادة توجيهك إلى المدونة إذا كنت متصلاً.
بنفس الطريقة ، يجب توفير إعادة توجيه بعد انقطاع الاتصال في وحدة التحكم نفسها:

<?php
protected $redirectAfterLogout = 'post';
يتم إنشاء المقالات في طريقة العرض باستخدام foreach :

@foreach($posts as $post)
    ...
@endforeach
إذا كنت تتصل بمستخدم ليس مسؤولًا (انظر في الجدول الخاص بك للعثور على واحد ، حيث أن مجموع المستخدمين عشوائيًا ، فلن نعرف مقدمًا من هو ومن لا). يمكنك العودة إلى المدونة باستخدام زرين إضافيين:
framework Laravel MVC
أزرار للمستخدم الأساسي
نستخدم شرطًا لتكييف الصفحة:

@if(Auth::check())
    ...
@else
    ...
@endif
تسمح طريقة check للفئة Auth تُمكّن من معرفة ما إذا كان المستخدم متصلاً.
هناك المساعد auth() الذي يوفر عنك استخدام الواجهة:

@if(auth()->check())
ينشئ الزر الأول « Créer un article » عنوان url :

.../post/create
هذا له تأثير الحصول على نموذج الإنشاء الذي سنراه قريبًا.
ينشئ الزر « Deconnexion »  الثاني عنوان url :

.../logout
وهو ما يتوافق أيضًا مع ما رأيناه في الفصل السابق.
إذا كان المستخدم الذي قام بتسجيل الدخول مسؤولاً ، فلديه أيضًا زر حذف لكل مقالة:
framework Laravel MVC
زر الحذف
ما زلنا نستخدم شرطًا لاكتشاف المسؤول:

@if(Auth::check() and Auth::user()->admin)
    ...
@endif 
يجب تسجيل دخول المستخدم ( check) وأن يكون مسؤولاً ( user()->admin) .
خططت لتأكيد الحذف مع القليل من javascript .
فيما يلي طريقة عرض نموذج إنشاء المقالة ( resources/views/posts/add.blade.php) :

@extends('template')

@section('contenu')
    <br>
    <div class="col-sm-offset-3 col-sm-6">
        <div class="panel panel-info">
            <div class="panel-heading">Ajout d'un article</div>
            <div class="panel-body"> 
                {!! Form::open(['route' => 'post.store']) !!}
                    <div class="form-group {!! $errors->has('titre') ? 'has-error' : '' !!}">
                        {!! Form::text('titre', null, ['class' => 'form-control', 'placeholder' => 'Titre']) !!}
                        {!! $errors->first('titre', '<small class="help-block">:message</small>') !!}
                    </div>
                    <div class="form-group {!! $errors->has('contenu') ? 'has-error' : '' !!}">
                        {!! Form::textarea ('contenu', null, ['class' => 'form-control', 'placeholder' => 'Contenu']) !!}
                        {!! $errors->first('contenu', '<small class="help-block">:message</small>') !!}
                    </div>
                    {!! Form::submit('Envoyer !', ['class' => 'btn btn-info pull-right']) !!}
                {!! Form::close() !!}
            </div>
        </div>
        <a href="javascript:history.back()" class="btn btn-primary">
            <span class="glyphicon glyphicon-circle-arrow-left"></span> Retour
        </a>
    </div>
@endsection
لا يوجد شيء جديد حول هذا العرض. إليك كيف يبدو:
framework Laravel MVC
نموذج إنشاء المقال
يمكننا إدخال العنوان والمحتوى الذي سيتم التحقق من صحته في وحدة التحكم وحفظه إذا سارت الأمور على ما يرام.
في بعض الأحيان لا يتم إنشاء طرق العرض بشكل صحيح. يستخدم Laravel ذاكرة التخزين المؤقت لطرق العرض   storage/framework/views . يمكنك حذف جميع الملفات بأمان (ولكن ليس   .gitignore  ) لإجبار Laravel على إنشاء طرق عرض جديدة. هناك أمر Artisan للقيام بذلك:

php artisan view:clear

في الخلاصة


  • تتطلب علاقة النوع  1: n  إنشاء مفتاح خارجي على الجانب n  .
  • يمكنك ملء جداول التسجيل بمجموع المستخدمين.
  • تتطلب العلاقة في الأساس تنفيذ أساليب خاصة في النماذج.
  • مع الوسيطة من السهل إدارة الوصول إلى أساليب التحكم.