برنامه نویسی

لاراول برای مبتدیان شماره 4 – یک داشبورد ایجاد کنید

کد منبع را از اینجا دانلود کنید. ⬅️

بالاخره نوبت به مهم ترین قسمت این آموزش می رسد. بیایید یک برنامه وبلاگ کاملاً برجسته با پست ها، دسته بندی ها و همچنین برچسب ها ایجاد کنیم. قبلاً در مورد عملیات CRUD برای پست ها صحبت کردیم و در این مقاله قصد داریم آن را برای دسته ها و برچسب ها تکرار کنیم و همچنین نحوه برخورد با روابط بین آنها را نیز مورد بحث قرار می دهیم.

یک پروژه جدید لاراول را راه اندازی کنید

یک بار دیگر، ما با یک پروژه جدید شروع می کنیم. یک پوشه کاری ایجاد کنید و آن را تغییر دهید. مطمئن شوید که Docker فعال است و سپس دستور زیر را اجرا کنید:

curl -s https://laravel.build/<app_name> | bash
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به فهرست برنامه تغییر دهید و سرور را راه اندازی کنید.

cd <app_name>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

./vendor/bin/sail up
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برای آسان‌تر کردن کارها، بیایید یک نام مستعار برای آن ایجاد کنیم sail. دستور زیر را اجرا کنید:

alias sail="[ -f sail ] && sh sail || sh vendor/bin/sail"
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

از این پس می‌توانید بدون مشخص کردن کل مسیر، مستقیماً بادبان را اجرا کنید.

sail up
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

احراز هویت کاربر

مرحله دوم، همانطور که قبلا ذکر کردیم، لاراول با یک اکوسیستم بزرگ عرضه می شود، و Laravel Breeze بخشی از این اکوسیستم است. این یک راه سریع برای تنظیم احراز هویت و ثبت نام کاربر در برنامه لاراول ارائه می دهد.

Breeze شامل نماها و کنترلرهای احراز هویت از پیش ساخته شده، و همچنین مجموعه ای از APIهای پشتیبان برای رسیدگی به احراز هویت و ثبت نام کاربر است. بسته به گونه ای طراحی شده است که نصب و پیکربندی آسان و با حداقل تنظیمات مورد نیاز باشد.

برای نصب Laravel Breeze از دستورات زیر استفاده کنید:

sail composer require laravel/breeze --dev
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

sail artisan breeze:install
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

sail artisan migrate
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

sail npm install
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

sail npm run dev
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این فرآیند به طور خودکار کنترلرهای مورد نیاز، میان افزارها و نماهایی را که برای ایجاد یک سیستم احراز هویت اولیه کاربر ضروری هستند، تولید می کند. با مراجعه به صفحه ثبت نام می توانید وارد شوید http://127.0.0.1/register.

ثبت نام لاراول بریز

یک حساب کاربری جدید ثبت کنید و به داشبورد هدایت خواهید شد.

در این مقاله قصد نداریم دقیقاً درباره نحوه عملکرد این سیستم احراز هویت کاربر بحث کنیم، زیرا به مفاهیم نسبتاً پیشرفته مربوط می شود. اما به شدت توصیه می شود که نگاهی به فایل های تولید شده بیندازید، آنها بینش عمیق تری از نحوه کار چیزها در لاراول به شما ارائه می دهند.

راه اندازی پایگاه داده

در مرحله بعد، باید تصویری بزرگ از ظاهر برنامه وبلاگمان داشته باشیم. ابتدا باید پایگاه داده ای داشته باشیم که بتواند پست ها، دسته ها و برچسب ها را ذخیره کند. هر جدول پایگاه داده ساختار زیر را دارد:

نوشته ها

کلید نوع
شناسه bigInteger
ایجاد شده در
updated_at
عنوان رشته
پوشش رشته
محتوا متن
منتشر شده است بولی

دسته بندی ها

کلید نوع
شناسه bigInteger
ایجاد شده در
updated_at
نام رشته

برچسب ها

کلید نوع
شناسه bigInteger
ایجاد شده در
updated_at
نام رشته

و البته، باید جدول کاربران نیز وجود داشته باشد، اما قبلاً توسط Laravel Breeze برای ما ساخته شده است، بنابراین این بار از آن می گذریم.

این جداول نیز همانطور که در لیست زیر نشان داده شده است با یکدیگر رابطه دارند:

  • هر کاربر دارای چندین پست است
  • هر دسته دارای پست های زیادی است
  • هر تگ دارای پست های زیادی است
  • هر پست متعلق به یک کاربر است
  • هر پست متعلق به یک دسته است
  • هر پست دارای برچسب های زیادی است

برای ایجاد این روابط، باید جدول پست ها را اصلاح کنیم:

پست هایی با روابط

کلید نوع
شناسه bigInteger
ایجاد شده در
updated_at
عنوان رشته
پوشش رشته
محتوا متن
منتشر شده است بولی
شناسه کاربر bigInteger
category_id bigInteger

و همچنین به یک جدول جداگانه برای رابطه پست/تگ نیاز داریم:

پست/برچسب

کلید نوع
post_id bigInteger
tag_id bigInteger

پیاده سازی ساختار پایگاه داده

برای پیاده سازی این طرح، مدل ها و فایل های مهاجرت را با استفاده از دستورات زیر تولید کنید:

sail artisan make:model Post --migration
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

sail artisan make:model Category --migration
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

sail artisan make:model Tag --migration
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و یک فایل مهاجرت جداگانه برای post_tag جدول:

sail artisan make:migration create_post_tag_table
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

database/migrations/create_posts_table.php

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('title');
            $table->string('cover');
            $table->text('content');
            $table->boolean('is_published');

            $table->bigInteger('user_id');
            $table->bigInteger('category_id');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

database/migrations/create_categories_table.php

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('categories');
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

database/migrations/create_tags_table.php

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('tags', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('tags');
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

database/migrations/create_post_tag_table.php

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('post_tag', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->bigInteger('post_id');
            $table->bigInteger('tag_id');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('post_tag');
    }
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این تغییرات را با دستور زیر اعمال کنید:

sail artisan migrate
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و سپس برای مدل های مربوطه، باید انتساب انبوه را برای فیلدهای انتخاب شده فعال کنیم تا بتوانیم از آن استفاده کنیم create یا update روش هایی که در مورد آنها وجود دارد، همانطور که در آموزش های قبلی در مورد آنها صحبت کردیم. و همچنین باید روابط بین جداول پایگاه داده را تعریف کنیم.

app/Models/Post.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Post extends Model
{
    use HasFactory;

    protected $fillable = [
        "title",
        'content',
        'cover',
        'is_published'
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }

    public function tags(): BelongsToMany
    {
        return $this->belongsToMany(Tag::class);
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

app/Models/Category.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Category extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
    ];

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

app/Models/Tag.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Tag extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
    ];

    public function posts(): BelongsToMany
    {
        return $this->belongsToMany(Post::class);
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

app/Models/User.php

<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کنترلرها و مسیرها

در مورد کنترل‌کننده‌ها، برای هر منبع (پست، دسته و برچسب) به یک کنترل‌کننده منبع نیاز داریم.

php artisan make:controller PostController --resource
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

php artisan make:controller CategoryController --resource
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

php artisan make:controller TagController --resource
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سپس مسیرهایی را برای هر یک از این کنترلرها ایجاد کنید:

routes/web.php

<?php

use App\Http\Controllers\CategoryController;
use App\Http\Controllers\PostController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\TagController;
use Illuminate\Support\Facades\Route;

// Dashboard routes
Route::prefix('dashboard')->group(function () {

    // Dashboard homepage
    Route::get("https://dev.to/", function () {
        return view('dashboard');
    })->name('dashboard');

    // Dashboard category resource
    Route::resource('categories', CategoryController::class);

    // Dashboard tag resource
    Route::resource('tags', TagController::class);

    // Dashboard post resource
    Route::resource('posts', PostController::class);

})->middleware(['auth', 'verified']);

Route::middleware('auth')->group(function () {
    Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
    Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
    Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});

require __DIR__ . '/auth.php';
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توجه داشته باشید که تمام مسیرها با a گروه بندی می شوند /dashboard پیشوند، و گروه دارای یک میان افزار است auth، به این معنی که کاربر برای دسترسی به داشبورد باید وارد سیستم شود.

کنترل کننده های دسته/برچسب

این CategoryController و TagController نسبتاً سرراست هستند. شما می توانید آنها را به همان روشی که ما ایجاد کردیم تنظیم کنید PostController در مقاله قبلی

app/Http/Controllers/CategoryController.php

<?php

namespace App\Http\Controllers;

use App\Models\Category;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class CategoryController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(): View
    {
        $categories = Category::all();

        return view('categories.index', [
            'categories' => $categories
        ]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): View
    {
        return view('categories.create');
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        // Get the data from the request
        $name = $request->input('name');

        // Create a new Post instance and put the requested data to the corresponding column
        $category = new Category();
        $category->name = $name;

        // Save the data
        $category->save();

        return redirect()->route('categories.index');
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id): View
    {
        $category = Category::all()->find($id);
        $posts = $category->posts();

        return view('categories.show', [
            'category' => $category,
            'posts' => $posts
        ]);
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(string $id): View
    {
        $category = Category::all()->find($id);

        return view('categories.edit', [
            'category' => $category
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id): RedirectResponse
    {
        // Get the data from the request
        $name = $request->input('name');

        // Find the requested category and put the requested data to the corresponding column
        $category = Category::all()->find($id);
        $category->name = $name;

        // Save the data
        $category->save();

        return redirect()->route('categories.index');
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id): RedirectResponse
    {
        $category = Category::all()->find($id);

        $category->delete();

        return redirect()->route('categories.index');
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

app/Http/Controllers/TagController.php

<?php

namespace App\Http\Controllers;

use App\Models\Tag;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class TagController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(): View
    {
        $tags = Tag::all();

        return view('tags.index', [
            'tags' => $tags
        ]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): View
    {
        return view('tags.create');
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        // Get the data from the request
        $name = $request->input('name');

        // Create a new Post instance and put the requested data to the corresponding column
        $tag = new Tag();
        $tag->name = $name;

        // Save the data
        $tag->save();

        return redirect()->route('tags.index');
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id): View
    {
        $tag = Tag::all()->find($id);
        $posts = $tag->posts();

        return view('tags.show', [
            'tag' => $tag,
            'posts' => $posts
        ]);
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(string $id): View
    {
        $tag = Tag::all()->find($id);

        return view('tags.edit', [
            'tag' => $tag
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id): RedirectResponse
    {
        // Get the data from the request
        $name = $request->input('name');

        // Find the requested category and put the requested data to the corresponding column
        $tag = Tag::all()->find($id);
        $tag->name = $name;

        // Save the data
        $tag->save();

        return redirect()->route('tags.index');
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id): RedirectResponse
    {
        $tag = Tag::all()->find($id);

        $tag->delete();

        return redirect()->route('tags.index');
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به یاد داشته باشید که با استفاده از دستور زیر می توانید نام مسیرها را بررسی کنید:

sail artisan route:list
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کنترلر پست

از طرف دیگر، PostController کمی پیچیده تر است، زیرا شما باید با آپلود تصاویر و روابط در store() روش. بیایید نگاه دقیق تری بیندازیم:

app/Http/Controllers/PostController.php

<?php

namespace App\Http\Controllers;

use App\Models\Category;
use App\Models\Post;
use App\Models\Tag;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Builder;

class PostController extends Controller
{
    . . .

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        // Get the data from the request
        $title = $request->input('title');
        $content = $request->input('content');

        if ($request->input('is_published') == 'on') {
            $is_published = true;
        } else {
            $is_published = false;
        }

        // Create a new Post instance and put the requested data to the corresponding column
        $post = new Post();
        $post->title = $title;
        $post->content = $content;
        $post->is_published = $is_published;

        // Save the cover image
        $path = $request->file('cover')->store('cover', 'public');
        $post->cover = $path;

        // Set user
        $user = Auth::user();
        $post->user()->associate($user);

        // Set category
        $category = Category::find($request->input('category'));
        $post->category()->associate($category);

        // Save post
        $post->save();

        //Set tags
        $tags = $request->input('tags');

        foreach ($tags as $tag) {
            $post->tags()->attach($tag);
        }

        return redirect()->route('posts.index');
    }

    . . .
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در این مورد چند نکته قابل ذکر است store() روش. ابتدا، خط 28 تا 32، ما از یک چک باکس HTML برای نشان دادن آن استفاده می کنیم is_published فیلد، و مقادیر آن یکی هستند 'on' یا null. اما در پایگاه داده مقادیر آن به صورت ذخیره می شود true یا false، پس باید از an استفاده کنیم if بیانیه ای برای حل این موضوع

خط 41 تا 42 برای بازیابی فایل ها باید از file() روش به جای input()و فایل در قسمت ذخیره می شود public دیسک زیر دایرکتوری cover.

خط 45 تا 46، کاربر فعلی را دریافت کنید Auth::user()و پست را با کاربر استفاده کننده مرتبط کنید associate() روش. و خط 49 تا 50 همین کار را برای دسته انجام می دهد. به یاد داشته باشید که این کار را فقط از طریق می توانید انجام دهید $post و نه $user یا $category، از آنجا که user_id و category_id ستون ها در posts جدول.

در نهایت، برای تگ ها، همانطور که از خط 56 تا 60 نشان داده شد، باید پست فعلی را در پایگاه داده ذخیره کنید، و سپس لیستی از برچسب ها را بازیابی کنید و هر یک از آنها را یک به یک به پست پیوست کنید. attach() روش.

برای update() روش، همه چیز به طور مشابه کار می کند، با این تفاوت که قبل از اینکه بتوانید تگ های جدید را ضمیمه کنید، باید تمام تگ های موجود را حذف کنید.

$post->tags()->detach();
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بازدیدها

هنگام ساختن یک سیستم دید، همیشه به یاد داشته باشید که سازماندهی شده باشید. این ساختاری است که من با آن می روم:

resources/views
├── auth
├── categories
│   ├── create.blade.php
│   ├── edit.blade.php
│   ├── index.blade.php
│   └── show.blade.php
├── components
├── layouts
├── posts
│   ├── create.blade.php
│   ├── edit.blade.php
│   ├── index.blade.php
│   └── show.blade.php
├── profile
├── tags
│   ├── create.blade.php
│   ├── edit.blade.php
│   ├── index.blade.php
│   └── show.blade.php
├── dashboard.blade.php
└── welcome.blade.php
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

من سه دایرکتوری ایجاد کرده ام، posts، categories و tagsو هر کدام دارای چهار الگو هستند، create، edit، index و show (بجز posts از آنجایی که داشتن الف ضروری نیست show صفحه برای پست ها در داشبورد).

گنجاندن همه این نماها در یک مقاله این آموزش را غیر ضروری طولانی می کند، بنابراین در عوض، من فقط صفحات ایجاد، ویرایش و فهرست بندی پست ها را نشان می دهم. با این حال، در صورت نیاز به مرجع، کد منبع این آموزش به صورت رایگان در اینجا موجود است.

مشاهده ایجاد پست

resources/views/posts/create.blade.php

<x-app-layout>
    <x-slot name="header">
        <div class="flex justify-between">
            <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
                {{ __('Posts') }}
            </h2>
            <a href="{{ route('posts.create') }}">
                <x-primary-button>{{ __('New') }}</x-primary-button>
            </a>
        </div>

        <script src="https://cdn.tiny.cloud/. . ./tinymce.min.js" referrerpolicy="origin"></script>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
                <div class="">
                    <form action="{{ route('posts.store') }}" method="POST" class="mt-6 space-y-3" enctype="multipart/form-data">
                        {{ csrf_field() }}
                        <input type="checkbox" name="is_published" id="is_published">
                        <x-input-label for="is_published">Make this post public</x-input-label>
                        <br>
                        <x-input-label for="title">{{ __('Title') }}</x-input-label>
                        <x-text-input id="title" name="title" type="text" class="mt-1 block w-full" required autofocus autocomplete="name" />
                        <br>
                        <x-input-label for="content">{{ __('Content') }}</x-input-label>
                        <textarea name="content" id="content" cols="30" rows="30"></textarea>
                        <br>
                        <x-input-label for="cover">{{ __('Cover Image') }}</x-input-label>
                        <x-text-input id="cover" name="cover" type="file" class="mt-1 block w-full" required autofocus autocomplete="cover" />
                        <br>
                        <x-input-label for="category">{{ __('Category') }}</x-input-label>
                        <select id="category" name="category">
                            @foreach($categories as $category)
                            <option value="{{ $category->id }}">{{ $category->name }}</option>
                            @endforeach
                        </select>
                        <br>
                        <x-input-label for="tags">{{ __('Tags') }}</x-input-label>
                        <select id="tags" name="tags[]" multiple>
                            @foreach($tags as $tag)
                            <option value="{{ $tag->id }}">{{ $tag->name }}</option>
                            @endforeach
                        </select>
                        <br>
                        <x-primary-button>{{ __('Save') }}</x-primary-button>
                    </form>
                    <script>
                        tinymce.init({. . .});
                    </script>
                </div>
            </div>

        </div>
    </div>
</x-app-layout>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

من از TinyMCE به عنوان ویرایشگر متن غنی استفاده می کنم، می توانید آن را با چیز دیگری جایگزین کنید یا به سادگی از یک <textarea></textarea> در صورت تمایل

خط 19، این فرم باید داشته باشد enctype="multipart/form-data" از آنجایی که ما فقط متون را منتقل نمی کنیم، فایل ها نیز وجود دارد.

خط 31، به یاد داشته باشید که استفاده کنید type="file" اینجا از آنجایی که ما در حال آپلود یک تصویر هستیم.

در خط 34 تا 38، مقدار گزینه به backend منتقل می شود.

خط 41 تا 45، در اینجا باید به دو نکته توجه کنید. ابتدا توجه کنید name="tags[]"، [] به لاراول می گوید که یک آرایه تکرارپذیر را به جای متن ها منتقل کند. و دوم، multiple یک فرم چند انتخابی به جای انتخاب واحد مانند فرم دسته ها ایجاد می کند.

مشاهده ویرایش پست

resources/views/posts/edit.blade.php

<x-app-layout>
    <x-slot name="header">
        <div class="flex justify-between">
            <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
                {{ __('Posts') }}
            </h2>
            <a href="{{ route('posts.create') }}">
                <x-primary-button>{{ __('New') }}</x-primary-button>
            </a>
        </div>

        <script src="https://cdn.tiny.cloud/. . ./tinymce.min.js" referrerpolicy="origin"></script>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
                <div class="">
                    <form action="{{ route('posts.update', ['post' => $post->id]) }}" method="POST" class="mt-6 space-y-3" enctype="multipart/form-data">
                        {{ csrf_field() }}
                        {{ method_field('PUT') }}
                        <input type="checkbox" name="is_published" id="is_published" @checked($post->is_published)/>
                        <x-input-label for="is_published">Make this post public</x-input-label>
                        <br>
                        <x-input-label for="title">{{ __('Title') }}</x-input-label>
                        <x-text-input id="title" name="title" type="text" class="mt-1 block w-full" required autofocus autocomplete="name" value="{{ $post->title }}" />
                        <br>
                        <x-input-label for="content">{{ __('Content') }}</x-input-label>
                        <textarea name="content" id="content" cols="30" rows="30">{{ $post->content }}</textarea>
                        <br>
                        <x-input-label for="cover">{{ __('Update Cover Image') }}</x-input-label>
                        <img src="{{ Illuminate\Support\Facades\Storage::url($post->cover) }}" alt="cover image" width="200">
                        <x-text-input id="cover" name="cover" type="file" class="mt-1 block w-full" autofocus autocomplete="cover" />
                        <br>
                        <x-input-label for="category">{{ __('Category') }}</x-input-label>
                        <select id="category" name="category">
                            @foreach($categories as $category)
                            <option value="{{ $category->id }}" @selected($post->category->id == $category->id)>{{ $category->name }}</option>
                            @endforeach
                        </select>
                        <br>
                        <x-input-label for="tags">{{ __('Tags') }}</x-input-label>
                        <select id="tags" name="tags[]" multiple>
                            @foreach($tags as $tag)
                            <option value="{{ $tag->id }}" @selected($post->tags->contains($tag))>{{ $tag->name }}</option>
                            @endforeach
                        </select>
                        <br>
                        <x-primary-button>{{ __('Save') }}</x-primary-button>
                    </form>
                    <script>
                        tinymce.init({. . .});
                    </script>
                </div>
            </div>

        </div>
    </div>
</x-app-layout>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خط 19 تا 21، به طور پیش فرض، HTML از روش PUT پشتیبانی نمی کند، بنابراین کاری که می توانیم انجام دهیم استفاده از آن است. method="POST"و سپس به لاراول بگویید از روش PUT استفاده کند {{ method_field('PUT') }}.

نمای فهرست پست

resources/views/posts/index.blade.php

<x-app-layout>
    <x-slot name="header">
        <div class="flex justify-between">
            <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
                {{ __('Posts') }}
            </h2>
            <a href="{{ route('posts.create') }}">
                <x-primary-button>{{ __('New') }}</x-primary-button>
            </a>
        </div>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            @foreach($posts as $post)
            <div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg mb-4 px-4 h-20 flex justify-between items-center">
                <div class="text-gray-900 dark:text-gray-100">
                    <p>{{ $post->title }}</p>
                </div>
                <div class="space-x-2">
                    <a href="{{ route('posts.edit', ['post' => $post->id]) }}"> <x-primary-button>{{ __('Edit') }}</x-primary-button></a>
                    <form method="post" action="{{ route('posts.destroy', ['post' => $post->id]) }}" class="inline">
                        {{ csrf_field() }}
                        {{ method_field('DELETE') }}
                        <x-danger-button>
                            {{ __('Delete') }}
                        </x-danger-button>
                    </form>
                </div>
            </div>
            @endforeach
        </div>
    </div>
</x-app-layout>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به دکمه حذف توجه کنید، به جای دکمه معمولی، باید فرمی با متد DELETE باشد، زیرا یک پیوند معمولی فقط متد GET دارد.

با این نمایش، شما باید بتوانید بقیه سیستم دید را به راحتی بسازید.

اسکرین شات ها

آخرین اما نه کم اهمیت، در اینجا اسکرین شات هایی از داشبوردی که من ایجاد کرده ام آورده شده است.

خانه داشبورد

لیست دسته ها

ایجاد دسته

به روز رسانی پست

در مقاله بعدی، می‌خواهیم از داشبورد حرکت کنیم و قسمت جلویی برنامه را ایجاد کنیم که کاربر بتواند ببیند.

اگر این مقاله را دوست داشتید، لطفاً سایر آموزش های من را نیز بررسی کنید:

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا