لاراول برای مبتدیان شماره 3 – عملیات CRUD

کد منبع را از اینجا دانلود کنید. ⬅️
اکنون، در نهایت قصد داریم از همه چیزهایی که تاکنون در مورد لاراول یاد گرفتهایم استفاده کنیم و از آن برای ایجاد یک پروژه واقعی استفاده کنیم.
بیایید با چیز ساده تر شروع کنیم. در این مقاله قصد داریم یک وبلاگ کوچک بسازیم که فقط حاوی پستها و بدون دستهبندی یا برچسب است. هر پست یک عنوان و یک محتوا دارد. این یک برنامه وبلاگ با امکانات کامل نیست، اما از طریق این مثال، من دقیقا نحوه بازیابی داده ها از پایگاه داده، نحوه ایجاد/به روز رسانی اطلاعات جدید، نحوه ذخیره آنها در پایگاه داده و همچنین نحوه ذخیره آنها را نشان خواهم داد. برای حذف آنها
طراحی ساختار پایگاه داده
ابتدا بیایید به پایگاه داده بپردازیم. ما یک فایل مهاجرت برای آن ایجاد خواهیم کرد post
جدول. این جدول باید حاوی عنوان و محتوا باشد. با دستور زیر یک فایل مهاجرت ایجاد کنید:
php artisan make:migration create_posts_table
<?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->text('content');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
در این مثال، ما پنج ستون در آن ایجاد کردیم post
جدول:
-
id()
ایجاد می کندid
ستون، که معمولا برای نمایه سازی استفاده می شود. -
timestamps()
دو ستون ایجاد می کند،created_at
وuptated_at
. این دو ستون با ایجاد و به روز رسانی رکورد به طور خودکار به روز می شوند. -
string('title')
یک ستون ایجاد می کندtitle
با نوعVARCHAR
، که طول پیش فرض آن 255 بایت است. -
string('content')
ستون محتوا را ایجاد می کند.
برای اعمال تغییرات، دستور زیر را اجرا کنید:
php artisan migrate
و جدید posts
جدول باید تولید شود:
حال می توانیم مدل مربوط به این جدول را ایجاد کنیم.
php artisan make:model Post
app/Models/Post.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
}
و کنترل کننده منبع مربوطه را تولید کنید:
php artisan make:controller PostController --resource
در نهایت این کنترلر را در روتر ثبت کنید:
use App\Http\Controllers\PostController;
Route::resource('posts', PostController::class);
با اجرای دستور زیر می توانید بررسی کنید که چه مسیرهایی ثبت شده اند:
php artisan route:list
GET|HEAD posts ................................................................. posts.index › PostController@index
POST posts ................................................................. posts.store › PostController@store
GET|HEAD posts/create ........................................................ posts.create › PostController@create
GET|HEAD posts/{post} ............................................................ posts.show › PostController@show
PUT|PATCH posts/{post} ........................................................ posts.update › PostController@update
DELETE posts/{post} ...................................................... posts.destroy › PostController@destroy
GET|HEAD posts/{post}/edit ....................................................... posts.edit › PostController@edit
خروجی حاوی اطلاعاتی مانند روش های درخواست، روش های کنترل کننده و همچنین نام مسیرها است. این اطلاعات بسیار مهم هستند و در ادامه این مقاله به آنها نیاز خواهیم داشت.
عملیات CRUD
اکنون زمان آن رسیده است که به خود برنامه شیرجه بزنیم. هنگام ساخت برنامه های واقعی، بعید است که ابتدا همه کنترلرها را ایجاد کنید و سپس قالب ها را طراحی کنید و سپس به سراغ روترها بروید. در عوض، باید از دیدگاه کاربر فکر کنید و به این فکر کنید که کاربر ممکن است بخواهد چه اقداماتی انجام دهد.
به طور کلی، کاربر باید توانایی انجام چهار عملیات را برای هر منبع داشته باشد، که در مورد ما، این است Post
.
- ایجاد: کاربر باید بتواند منابع جدیدی ایجاد کرده و در پایگاه داده ذخیره کند.
- خواندن: کاربر باید بتواند منابع را بخواند، هم فهرستی از منابع را بازیابی کند و هم جزئیات یک منبع خاص را بررسی کند.
- به روز رسانی: کاربر باید بتواند منابع موجود را به روز کند و رکورد پایگاه داده مربوطه را به روز کند.
- حذف: کاربر باید بتواند یک منبع را از پایگاه داده حذف کند.
آنها با هم به عنوان عملیات CRUD شناخته می شوند.
عمل ایجاد
در حال حاضر، پایگاه داده ما هنوز خالی است، بنابراین کاربر ممکن است بخواهد پست های جدیدی ایجاد کند. بنابراین اجازه دهید با عمل ایجاد (C) شروع کنیم. برای تکمیل این اقدام ایجاد، به دو چیز نیاز دارید:
- آ
create()
روش کنترلر که فرمی را نمایش می دهد و به کاربر اجازه می دهد عنوان و محتوا را پر کند. - آ
store()
روش کنترلر، که پست جدید ایجاد شده را در پایگاه داده ذخیره می کند و کاربر را به صفحه لیست هدایت می کند.
این create()
روش با الگوی URL مطابقت دارد /posts/create
(GET
روش)، و store()
روش با URL مطابقت دارد /post
(POST
روش).
در اینجا یک بررسی مختصر در مورد روش های HTTP در صورتی که نیاز به تجدید نظر دارید آورده شده است:
- این
GET
متد رایج ترین روش درخواست HTTP است. برای درخواست داده ها و منابع از سرور استفاده می شود.- این
POST
روش برای ارسال داده ها به سرور استفاده می شود که برای ایجاد / به روز رسانی یک منبع استفاده می شود.- این
HEAD
روش درست مثلGET
روش. به جز پاسخ HTTP فقط شامل سر خواهد بود نه بدن. این روش معمولا توسط توسعه دهندگان برای اهداف اشکال زدایی استفاده می شود.- این
PUT
روش مشابه استPOST
، با یک تفاوت کوچک وقتی توPOST
منبعی که از قبل در سرور وجود دارد، این عمل هیچ تفاوتی ایجاد نمی کند. اینPUT
با این حال، هر بار که درخواستی را ارائه میکنید، آن منبع را کپی میکند.- این
DELETE
روش یک منبع را از سرور حذف می کند.
بیایید با شروع کنیم create()
روش:
app/Http/Controllers/PostController.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Contracts\View\View;
. . .
class PostController extends Controller
{
. . .
/**
* Show the form for creating a new resource.
*/
public function create(): View
{
return view('posts.create');
}
. . .
}
این متد زمانی اجرا می شود که شما a را ارسال کنید GET
درخواست به /posts/create
، و به دیدگاه اشاره می کند views/posts/create.blade.php
. خط 16 اطلاعیه، Response
به View تغییر کرده است زیرا این روش باید یک view را به جای آن برگرداند.
بعد، باید نمای مربوطه را ایجاد کنیم. می توانیم با آن شروع کنیم layout
:
views/layout.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
@yield('title')
</head>
<body class="container mx-auto font-serif">
<div class="bg-white text-black font-serif">
<div id="nav">
<nav class="flex flex-row justify-between h-16 items-center shadow-md">
<div class="px-5 text-2xl">
<a href="{{ route('posts.index') }}">
My Blog
</a>
</div>
<div class="hidden lg:flex content-between space-x-10 px-10 text-lg">
<a href="{{ route('posts.create') }}" class="hover:underline hover:underline-offset-1">New Post</a>
<a href="https://github.com/ericnanhu" class="hover:underline hover:underline-offset-1">GitHub</a>
</div>
</nav>
</div>
@yield('content')
<footer class="bg-gray-700 text-white">
<div
class="flex justify-center items-center sm:justify-between flex-wrap lg:max-w-screen-2xl mx-auto px-4 sm:px-8 py-10">
<p class="font-serif text-center mb-3 sm:mb-0">Copyright © <a href="https://www.ericsdevblog.com/"
class="hover:underline">Eric Hu</a></p>
<div class="flex justify-center space-x-4">
. . .
</div>
</div>
</footer>
</div>
</body>
</html>
خط 17 و 22، بریس های مجعد دوتایی ({{ }}
) به شما امکان می دهد کدهای PHP را در داخل قالب اجرا کنید، و در مورد، route('posts.index')
متد مسیری را که نام آن است برمی گرداند posts.index
. می توانید نام مسیرها را با مراجعه به خروجی بررسی کنید php artisan route:list
فرمان
بعد، بیایید به ادامه مطلب برویم create
چشم انداز. شما باید در اینجا سازماندهی کنید. از آنجایی که این create
view برای اعمال مربوط به پست است، من یک را ایجاد کردم post
دایرکتوری برای ذخیره این نمای.
views/posts/create.blade.php
@extends('layout')
@section('title')
<title>Create</title>
@endsection
@section('content')
<div class="w-96 mx-auto my-8">
<h2 class="text-2xl font-semibold underline mb-4">Create new post</h2>
<form action="{{ route('posts.store') }}" method="POST">
{{ csrf_field() }}
<label for="title">Title:</label><br>
<input type="text" id="title" name="title"
class="p-2 w-full bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300"><br>
<br>
<label for="content">Content:</label><br>
<textarea type="text" id="content" name="content" rows="15"
class="p-2 w-full bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300"></textarea><br>
<br>
<button type="submit"
class="font-sans text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-md text-sm w-full px-5 py-2.5 text-center">Submit</button>
</form>
</div>
@endsection
هنگام استفاده از فرم ها برای انتقال داده ها باید به چند نکته توجه کنیم.
در خط 10، ویژگی action تعریف میکند که هنگام ارسال این فرم چه اتفاقی میافتد و در این حالت به مرورگر دستور میدهد تا از مسیر بازدید کند. posts.store
، با یک POST
روش HTTP
خط 11، {{ csrf_field() }}
. CSRF یک حمله مخرب است که برنامه های کاربردی وب را هدف قرار می دهد و این csrf_field()
عملکرد در برابر آن نوع حمله محافظت می کند. در اینجا می توانید اطلاعات بیشتری در مورد CSRF (جعل درخواست بین سایتی) بخوانید.
به خط 13 و 17 توجه کنید name
صفت. هنگامی که فرم ارسال می شود، ورودی کاربر به متغیری گره می خورد که نام آن توسط متغیر مشخص شده است name
صفت. به عنوان مثال، زمانی که name="title"
، ورودی کاربر به متغیر گره خورده است title
و با استفاده از آن می توانیم به مقدار آن دسترسی پیدا کنیم $request->input('title')
. بعداً خواهیم دید که این دقیقاً چگونه کار می کند.
خط 20، type
ویژگی باید تنظیم شود submit
تا این فرم کار کند
حالا سرور توسعه دهنده را راه اندازی کنید و به آن بروید http://127.0.0.1:8000/posts/create
.
هنگامی که دکمه ارسال کلیک می شود، مرورگر یک را ارسال می کند POST
درخواست به سرور، و این بار، store()
روش اجرا خواهد شد. این POST
درخواست شامل ورودی کاربر خواهد بود و به این صورت می توان به آنها دسترسی داشت:
PostController.php
<?php
namespace App\Http\Controllers;
. . .
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');
// Create a new Post instance and put the requested data to the corresponding column
$post = new Post;
$post->title = $title;
$post->content = $content;
// Save the data
$post->save();
return redirect()->route('posts.index');
}
. . .
}
پس از ذخیره شدن داده ها، به مسیر هدایت می شوید posts.index
مسیر
به مرورگر خود بازگردید و عنوان و محتوای جدیدی را تایپ کنید و سپس روی دکمه ارسال کلیک کنید. این index
نمای هنوز ایجاد نشده است، بنابراین یک پیام خطا برگردانده خواهد شد. با این حال، اگر پایگاه داده را بررسی کنید، یک رکورد جدید باید اضافه شود.
اقدام لیست
بعد، بیایید روی عملیات خواندن (R) کار کنیم. در واقع دو نوع مختلف عملیات خواندن وجود دارد. اولین مورد، اقدام لیست است که فهرستی از تمام پست ها را به کاربر برمی گرداند. این عمل مربوط به index()
روش:
PostController.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class PostController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(): View
{
$posts = Post::all();
return view('posts.index', [
'posts' => $posts,
]);
}
. . .
}
و در اینجا مربوطه است index
چشم انداز:
views/post/index.blade.php
@extends('layout')
@section('title')
<title>Page Title</title>
@endsection
@section('content')
<div class="max-w-screen-lg mx-auto my-8">
@foreach($posts as $post)
<h2 class="text-2xl font-semibold underline mb-2"><a href="{{ route('posts.show', ['post' => $post->id]) }}">{{ $post->title }}</a></h2>
<p class="mb-4">{{ Illuminate\Support\Str::words($post->content, 100) }}</p>
@endforeach
</div>
@endsection
خط 9، foreach
روی همه بازیابی شده تکرار می شود $posts
و هر مقدار را به متغیر اختصاص دهید $post
.
خط 10، به نحوه پست توجه کنید id
به منتقل می شود posts.show
مسیر سپس مسیر این متغیر را به show()
روش کنترلر که در ادامه خواهید دید.
خط 11، Str::words()
متد یک کمک کننده PHP است و فقط 100 کلمه اول آن را می گیرد content
.
اکشن نمایشی
دومین عملیات خواندن، عمل نمایش است که جزئیات یک منبع خاص را نمایش می دهد. این عمل با show()
روش.
PostController.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class PostController extends Controller
{
. . .
/**
* Display the specified resource.
*/
public function show(string $id): View
{
$post = Post::all()->find($id);
return view('posts.show', [
'post' => $post,
]);
}
. . .
}
views/post/show.blade.php
@extends('layout')
@section('title')
<title>{{ $post->title }}</title>
@endsection
@section('content')
<div class="max-w-screen-lg mx-auto my-8">
<h2 class="text-2xl font-semibold underline mb-2">{{ $post->title }}</h2>
<p class="mb-4">{{ $post->content }}</p>
<div class="grid grid-cols-2 gap-x-2">
<a href="{{ route('posts.edit', ['post' => $post->id]) }}"
class="font-sans text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-md text-sm w-full px-5 py-2.5 text-center">Update</a>
<form action="{{ route('posts.destroy', ['post' => $post->id]) }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button type="submit"
class="font-sans text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-md text-sm w-full px-5 py-2.5 text-center">Delete</button>
</form>
</div>
</div>
@endsection
در اینجا باید به چند نکته توجه کنیم. ابتدا توجه کنید که چگونه به روز رسانی دکمه یک لینک ساده است، اما حذف دکمه یک فرم است. این به این دلیل است که یک پیوند به مرورگر میگوید که درخواست GET را به سرور ارسال کند، اما ما برای عمل حذف به چیز دیگری نیاز داریم.
بعد، اگر به داخل فرم نگاه کنید، متوجه می شوید که این فرم دارای است method="POST"
، اما برای عمل حذف به روش DELETE نیاز داریم. این به این دلیل است که به طور پیش فرض، HTML فقط از متدهای GET و POST پشتیبانی می کند و اگر به چیز دیگری نیاز دارید، باید تنظیم کنید. method="POST"
، و استفاده کنید method_field()
روش به جای
عمل به روز رسانی
بعد، برای عملیات به روز رسانی، ما باید edit()
روشی که یک فرم HTML را نمایش می دهد و update()
روشی که تغییراتی را در پایگاه داده ایجاد می کند.
PostController.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class PostController extends Controller
{
. . .
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id): View
{
$post = Post::all()->find($id);
return view('posts.edit', [
'post' => $post,
]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id): RedirectResponse
{
// Get the data from the request
$title = $request->input('title');
$content = $request->input('content');
// Find the requested post and put the requested data to the corresponding column
$post = Post::all()->find($id);
$post->title = $title;
$post->content = $content;
// Save the data
$post->save();
return redirect()->route('posts.show', ['post' => $id]);
}
. . .
}
views/post/edit.blade.php
@extends('layout')
@section('title')
<title>Edit</title>
@endsection
@section('content')
<div class="w-96 mx-auto my-8">
<h2 class="text-2xl font-semibold underline mb-4">Edit post</h2>
<form action="{{ route('posts.update', ['post' => $post->id]) }}" method="POST">
{{ csrf_field() }}
{{ method_field('PUT') }}
<label for="title">Title:</label><br>
<input type="text" id="title" name="title" value="{{ $post->title }}"
class="p-2 w-full bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300"><br>
<br>
<label for="content">Content:</label><br>
<textarea type="text" id="content" name="content" rows="15"
class="p-2 w-full bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300">{{ $post->content }}</textarea><br>
<br>
<button type="submit"
class="font-sans text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-md text-sm w-full px-5 py-2.5 text-center">Submit</button>
</form>
</div>
@endsection
عمل حذف
و در نهایت، destroy()
روش:
PostController.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class PostController extends Controller
{
. . .
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id): RedirectResponse
{
$post = Post::all()->find($id);
$post->delete();
return redirect()->route('posts.index');
}
}
این عمل نیازی به نما ندارد، زیرا فقط شما را به آن هدایت می کند posts.index
پس از اتمام عمل
اگر این مقاله را دوست داشتید، لطفاً سایر آموزش های من را نیز بررسی کنید: