در بخش اول از آموزش ساخت یک وبلاگ ساده با لاراول 5 ما نصب لاراول ، ایجاد Migrations ها ، ساخت مدل ها ، Eloquent ORM و Database Seeding رو توضیح دادیم و در این قسمت میخوایم بخش کنترل ها رو توضیح بدیم .
- ساخت کنترل ها
در لاراول ما کنترل ها رو با گسترش کلاس Controller که در دایرکتوری (app/http/controllers) قرار داره ایجاد میکنیم . همه کنترل های بوجود اومده در (app/http/controllers) قرار میگیرن .
نکته : لاراول هیچ محدودیتی در ساختار دایرکتوری خودش ندارو ، توسعه دهنده های میتونن به هر صورتی که بخوان دایرکتوری لاراول رو تنظیم مجدد کنن .
یک مثال از یه کنترل ساده :
<?php namespace App\Http\Controllers;
use ...
//file: app/Http/controllers/IndexController.php
class IndexController extends Controller {
public function showIndex()
{
// generates response from index.blade.php
return view('index');
}
}
//file: app/Http/routes.php
//registering route to controller actions
get('index','IndexController@showIndex');
//In general
get('route.name','SomeController@someAction');
post('route.name','SomeController@someAction');
بنابراین هر action در داخل کنترل ها دارای حدافل یه مسیر در فایل app/http/routes.php هستن . همچنین در بعضی مواقع ما با قرار دادن پیشوند به اول هر action بصورت ساده مسیر دلخواهو میسازیم . به کد زیر توجه کنید
<?php namespace App\Http\Controllers;
use ...
class IndexController extends Controller {
public function getAction()
{
//get request handling
}
public function postAction()
{
//post request handling
}
}
//registering route
Route::controller('index','IndexController);
به کد بالا نگاه کنید ما برای ثبت مسیر برای هر عمل در کنترل یه پیشوند برای هر عمل قرار دادیم و با استفاده از Route::controller('index','IndexController) بطور خودکار مسیر دهی ها رو با توجه به اون پیشوند ها خود برنامه انجام میده .
چند نکته :
- بطور معمول هر action با یه view همراه که این view کار نمایش دادن اطلاعات به کاربر رو انجام میده.
- هنگامی که ما یه آرایه رو با استفاده از return برمیگردونیم . این آرایه بطور خودکار با JSON کد گذاری و به ما نشون داده میشه .
- ما با استفاده از متد nest() متونیم یه view رو به یه متغیر نسبت بدیم .
- ساخت Controller ها برای برنامه
ما در قدم اول برای شروع کنترل BlogController رو میسازیم که وظیفه رسیدگی به درخواست اول رو داره : نشون دادن صفحه اصلی / محتوایی کلی وبسایت ، قسمت سرچ و نمایش سرچ رو به عهده داره . در قدم بعد ما به ترتیب مسئولیت رسیدگی به عملیات CRUD پست ها و نظرات رو به PostsController و CommentsController میدیم .
BlogController
کد زیر متعلق به کنترل BlogController که در قسمت app/http/Controllers/BlogController.php قرار داره .
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\post;
use Illuminate\Http\Request;
class BlogController extends Controller
{
/**
* select 10 post
* @return Home page
*/
public function getIndex()
{
$posts = post::orderBy('id', 'desc')->paginate(10);
return view('home')->nest('content', 'index', compact('posts','title'))
->with('title','Home Page | Laravel 5 Blog');
}
/**
* @param request serch
* @return result serch
*/
public function getSearch(Request $request)
{
$searchTerm = $request['s'];
$posts = Post::whereRaw('match(title,content) against(? in boolean mode)', [$searchTerm])
->paginate(10);
$posts->appends(['s' => $searchTerm]);
return view('home')
->nest('content', 'index', ($posts->isEmpty()) ? ['notFound' => true] : compact('posts'))
->with('title', 'Search: ' . $searchTerm);;
}
}
زمانی که ما مسیر خودمونو با Route::controller() به صورت Route::controller('/','BlogController') ثبت کنیم . getIndex() از مسیر نقشه برداری میکنه . بعد از اینکه آدرس صفحه اصلی سایت رو اجرا کردیم این action عمل میکنه و محتوایی مورد نظر رو بهتون نشون میده . در داخل getIndex() ما با استفاده از مدل post پست های خودمونو بازیابی میکنم . حالا این کار با استفاده از orderBy('id', 'desc') که باعث مرتبط شدن پست ها براساس شماره id و همینطور برای اینکه تمام مطالب تو یه صفحه نباشه از متد paginate() استفاده میکنیم و عدد 10 رو براش در نظر میگیریم تا در هر صفحه فقط 10 تا پست نمایش داده بشه . بعد از بازیابی اطلاعات اونو تو متغییر $posts قرار میدیم تا تو بخش view بتونیم با استفاده از یه حلقه به راحتی محتوای هر پست رو جدا کنیم و نمایش بدیم حالا قسمت view رو در آینده توضیح میدم . خوب ما با استفاده از return و متد view() صفحه Home.blade.php رو بازیابی و با متد nest() اطلاعات مورد نظرو براش میفرستیم .
ما با استفاده از getSearch() قابلیت جستجو در سایت رو برای کاربرا به وجود میاریم . ما از مدل Post برای ارسال کوئری برای جستجو استفاده میکنیم و همچنین از متد whereRaw() برای پیدا کردن محتوای مورد نظرمون بر اساس شرایط نوع جستجومتنی که مد نظرمون هست استفاده میکنیم و در آخر هم برای صفحه بندی نتایج جستجو از متد paginate() بهره میبریم . بقیه کد ها هم که مشخصه برای ارسال و نمایش اطلاعات بازیابی شده استفاده میشه .
The PostsController
کد زیر مربوط به کنترل PostsController می باشد :
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Requests\PostRequest;
use App\Post;
class PostController extends Controller {
/* get functions */
public function listPost()
{
$posts = post::orderBy('id', 'desc')->paginate(10);
return view('dash')->nest('content', 'posts.list', compact('posts'))
->with('title','Post listings');
}
/**
* @param post $post
* @return $this
*/
public function showPost(post $post)
{
$comments = $post->comments()->where('approved', '=', 1)->get();
return view('home')->nest('content', 'posts.single', compact('post', 'comments'))
->with('title',$post->title);
}
public function newPost()
{
return view('dash')->nest('content', 'posts.new')
->with('title', 'New Post');
}
public function editPost(post $post)
{
return view('dash')->nest('content', 'posts.edit', compact('post'))
->with('title', 'Edit Post');
}
public function deletePost(post $post)
{
$post->delete();
return redirect()->route('post.list')->with('success', 'Post is deleted!');
}
/**
* @param PostRequest $request
* post functions
* @return \Illuminate\Http\RedirectResponse
*/
public function savePost(PostRequest $request)
{
$post = [
'title' => $request['title'],
'content' => $request['content'],
];
$post = new Post($post);
$post->comment_count = 0;
$post->read_more = (strlen($post->content) > 120) ? substr($post->content, 0, 120) : $post->content;
$post->save();
return redirect('admin/dash-board')->with('success', 'Post is saved!');
}
public function updatePost(post $post,PostRequest $request)
{
$data = [
'title' => $request['title'],
'content' => $request['content'],
];
$post->title = $data['title'];
$post->content = $data['content'];
$post->read_more = (strlen($post->content) > 120) ? substr($post->content, 0, 120) : $post->content;
if (count($post->getDirty()) > 0) /* avoiding resubmission of same content */ {
$post->save();
return redirect()->back()->with('success', 'Post is updated!');
} else
return redirect()->back()->with('success', 'Nothing to update!');
}
}
نکته : اگه به کد های بالا نگاه کرده باشین تو بعضی از این عمل ها post $post رو به عنوان پارامتر میگیره ! خب این کار برای چیه !؟ خوشبختانه لاراول یه خوبی داره اینکه شما می تونید پارامتر های که برای Route ها مشخص میکنین و احتاج به اتصال به model دارن رو به راحتی به هم متصل کنید و در view بطور مستقیم ازش استفاده کنید . برای مثال ما از $router->model('post','App\Post') که تو فایل RouteServiceProvider.php (این فایل در app/Providers) ثبت میشه استفاده میکنیم . به این کار Route Model Bindings که ایشالله در موردش بعدا صحبت میکنیم فعلا به کد زیر دقت کنید:
<?php namespace App\Providers;
use Illuminate\Routing\Router;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider {
/**
* This namespace is applied to the controller routes in your routes file.
*
* In addition, it is set as the URL generator's root namespace.
*
* @var string
*/
protected $namespace = 'App\Http\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
*
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function boot(Router $router)
{
parent::boot($router);
$router->model('post','App\Post');
حالا زمانی که ما یه مسیر رو بازدید کنیم که پارامتری داره و اون پارامتر باید با مدلش ارتباط بر قرار کنه فقط با گذاشتن post $post در action به عنوان پارامتر و استفاده از اون در view کارمونو خیلی ساده و راحت میکنیم .
تنها action عمومی که در این کنترل قرار داره showPost که ما با استفاده از اون برای نمایش یه پست تنها استفاده میکنیم . در داخل showPost() ما با استفاده از Route Model Bindings که در بالا گفتیم پست مورد نظرمونو بازیابی میکنیم و با استفاده از $post->comments() و متد where نظرات مرتبط به اون پست که توسط مدیر تایید شدن رو هم بازیابی میکنیم خب اگه براتون سوال شد که چطوری این دوتا جدول با به هم اتصال پیدا کردن باید بگم که با استفاده از Relationships که تو قسمت اول کد اتصال دو جدول رو در هر مدل نوشتیم . البته Relationships رو تو یه پست جدا بصورت کامل توضیح میدم اما فعلا دونستن چطوری ارتباط این دو تا جدول کافیه براتون و در آخرم اطلاعات رو به صفحه (app/views/posts/single.blade.php) میفرسیتم .
action های باقی مونده در این کنترل برای انجام عملیات CRUD در بخش مدیریت هستن . برای مثال ما از listPost برای نشون دادن لیست پست های موجود در سایت بصورت یه جدول استفاده میکنیم ک همین جدول خودش شامل مسیر های برای حذف و آپدیت میشه .
ما از عمل newPost برای نشون دادن یه فرم به ادمین استفاده میکنیم تا ادمین بتونه با پرکردن و ارسال اون یه پست جدید بوجود بیاره . در داخل اون فرم برای ارسال مسیر savePost قرار داره که کار ذخیره کردن اون پست ارسالی از طرف ادمین رو انجام میده البته بعد از ارسال فرم در savePost که دارای پارامتر PostRequest اعتبار سنجی و اگه مشکلی نداشت در دیتابیس ثبت میشه .
نکته : Request به تازگی در لاراول 5 معرفی شدن و کارایی و سرعت عمل توسعه دهنده رو خیلی بالا میبره ،البته بعدا بصورت کامل به توضیح این ویژگی جدید لاراول 5 می پردازیم .
CommentsController
کد مربوط به کنترل CommentsController :
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Comment;
use App\Post;
use App\Http\Requests\CommentRequest;
use Illuminate\Http\Request;
class CommentController extends Controller {
/* get functions */
public function listComment()
{
$comments = Comment::orderBy('id', 'desc')->paginate(20);
return view('dash')->nest('content', 'comments.list', compact('comments'))
->with('title','Comment Listings');
}
public function newComment(Post $post,CommentRequest $request )
{
Comment::create($request->all());
/* redirect back to the form portion of the page */
return redirect()->back()
->with('success', 'Comment has been submitted and waiting for approval!');
}
public function showComment(Comment $comment,Request $request)
{
if ($request->ajax())
return view('comments.show', compact('comment'));
// handle non-ajax calls here
//else{}
}
public function deleteComment(Comment $comment)
{
$post = $comment->post;
$status = $comment->approved;
$comment->delete();
($status === 'yes') ? $post->decrement('comment_count') : '';
return redirect()->back()->with('success', 'Comment deleted!');
}
/* post functions */
public function updateComment(Comment $comment,Request $request)
{
$comment->approved = $request['status'];
$comment->save();
$comment->post->comment_count = Comment::where('post_id', '=', $comment->post->id)
->where('approved', '=', 1)->count();
$comment->post->save();
return redirect()->back()->with('success', 'Comment ' . (($comment->approved === 'yes') ? 'Approved' : 'Disapproved'));
}
}
در کد بالا : listComment برای نمایش لیست کامنت ها به مدیر استفاده و شامل یه جدوله که توش لینک اعمال CRUD برای هر کامت وجود داره . زمانی که یه دیدگاه جدید برای یه پست که تو وبسایت قرار داره بخواد ثبت بشه از عمل newComment برای اعتبار سنجی محتوایی اون کامنت و ثبت اون کامنت در دیتابیس استفاده میشه . newComment بعد از اعتبار سنجی و زمانی که در حال ثبت تو دیتابیسه ما approved برابر با 'No' قرار میدیم تا قبل تایید به نمایش در نیاین . بعد مدیر میتونه در پنل مدیریت با استفاده از updateComment اون کامنت رو تایید کنه البته updateComment بعد از هر تغییر تعداد کامنت های تایید شده برای اون پست رو میشماره و تو جدول پست مربوط به همون نظر تو ستون comment_count ثبت میکنه . deleteComment هم برای حذف کامنت مورد استفاده قرار میگیره .
در آخر عمل showComment که کارش نشون دادن یه دیده کلی از مشخصات ارسال کننده کامنت و محتوایی کامنته که بصورت آژاکس این درخواست ارسال و نمایش داده میشه . که ما این رو تو قسمت های بعد توضیح میدیم .
ممنون از این که تا اینجایی این قسمت هم همراه ما بودید . در بخش بعد ما در مورد routing ها صحبت میکنیمو میگیم برای این پروژه به چه routing نیازه .
سوالات ، مشکلات ، نظرات و انتقاد های خودتونو لطفا تو بخش نظرات همین پست مطرح کنید تا دوستان دیگه هم بتونن ازش استفاده کنن . با تشکر
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید