امروزه برنامه های تحت وب از روش های مختلفی برای پیاده سازی قابلیت علاقه مندی / لایک و ... در وب سایت شان استفاده می کنند.
این قابلیت ها را می توانید در وب سایت هایی نظیر Medium، فیسبوک، laracast و حتی روی roxo.ir ببینید. در این آموزش به شما نشان می دهیم که چگونه قابلیت favorite را با استفاده از لاراول و vue.js در وب سایت شما پیاده کنید.
اگر چه در این آموزش از واژه favorite استفاده می کنیم، اما شما میتوانید برای لایک و ... هم از این آموزش استفاده کنید.
در این آموزش یک برنامه وبلاگ ساده خواهیم ساخت. در این برنامه کاربران می توانند پست های جدید ایجاد کرده و همچنین پست های وبلاگ را favorite (افزودن به علاقه مندی ها) کنند. در نهایت کاربران می توانند پست هایی که Favorite کردن را مشاهده کنند.
این برنامه از یک مدل User و یک مدل Post استفاده می کند، همچنین یک سیستم احراز هویت در برنامه وجود دارد که تنها به کاربرانی که احراز هویت شده اند اجازه می دهد پست ها را favorite کرده و یا از حالت favorite خارج کنند.
همچنین با استفاده از Vue.js و Axios پست ها را بطور پویا (دینامیک) و بدون رفرش شدن صفحه، Favorite کرده و یا از حالت Favorite خارج می کنیم.
قبل از شروع کار، ابتدا به برنامه نهایی که قصد ساخت آن را داریم، نگاهی بیندازید:
ترمینال را باز کرده و یک پروژه جدید لاراول به نام laravel-vue-favorite ایجاد کنید.
laravel new laravel-vue-favorite
هنگام نصب لاراول، به طور خودکار برخی کتابخانه های مربوط به بخش Front end هم ساخته می شود. برخی از این کتابخانه ها عبارتند از:Bootstrap،VueJs، Axios که در ای آموزش ما از آنها استفاده می کنیم. اما باید ابتدا آنها را با دستور زیر نصب کنیم:
npm install
همچنین با استفاده از laravel mix، فایل های css و جاوا اسکریپت را کامپایل می کنیم. دستور فوق تمام وابستگی های laravel mix را هم نصب می کند.
برای این برنامه، نیاز به ساخت مدل های User، Post و Favorite داریم. همجنین باید فایل migration هر کدام را هم ایجاد کنیم.
php artisan make:model Post -m php artisan make:model Favorite -m
دستور فوق یک مدل Post و Favorite به همراه فایل migration مربوط به هر کدام را ایجاد می کند.
فایل migration مربوط به مدل Post را باز کرده و کدهای زیر را داخل متد up() آن بنویسید.
/** * Define posts table schema */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->string('title'); $table->text('body'); $table->timestamps(); }); }
جدول posts شامل یک id یا شناسه (user_id کاربری که پست را ایجاد کرده است)، title، body و چند ستون دیگر است.
سپس فایل migration مربوط به مدل Favorite را باز کرده و کدهای زیر را داخل متد up() آن بنویسید.
/** * Define favorites table schema */ public function up() { Schema::create('favorites', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->integer('post_id')->unsigned(); $table->timestamps(); }); }
جدول favorite یک جدول pivot است. این جدول دو ستون دارد: user_id که id کاربری که یک پست را Favorite کرده، نگه می دارد و post_id هم id پستی که favorite شده را نگهداری می کند.
برای فایل migration مربوط به مدل User از فایل پیش فرضی که لاراول ایجاد کرده است، استفاده میکنیم.
قبل از اجرای migration باید ابتدا پیکربندی های مربوط به پایگاه داده ها را انجام دهیم. کدهای زیر را به فایل .env اضافه کنید:
DB_DATABASE=laravue DB_USERNAME=root DB_PASSWORD=root
حال می توانید Migration ها را اجرا کنید:
php artisan migrate
در این مرحله قصد داریم داده های ساختگی برای برنامه ایجاد کرده تا بتوانیم اقدام به تست برنامه بکنیم. برای تولید داده های ساختگی از Model Factory استفاده می کنیم. Model Factory ها از یک کتابخانه PHP به نام faker برای تولید داده های ساختگی استفاده می کند.
داده های ساختگی را برای کاربران و پست ها ایجاد می کنیم.
هنگامی که فایل database/factories/ModelFactory.php را باز کنید، می بینید که لاراول یک factory برای مدل User ایجاد کرده است، و ما تنها برای مدل Post باید factory ایجاد کنیم. کدهای زیر را به فایل ModelFactory.php بعد از Factory مربوط به مدلUser، اضافه کنید:
// database/factories/ModelFactory.php $factory->define(App\Post::class, function (Faker\Generator $faker) { // Get a random user $user = \App\User::inRandomOrder()->first(); // generate fake data for post return [ 'user_id' => $user->id, 'title' => $faker->sentence, 'body' => $faker->text, ]; });
هطور که قبلاً دیدید، در فایل migration مربوط به مدل Post، تعریف کردیم که هر پست باید یک user_id داشته باشد. بنابراین ما یک کاربر تصادفی را گرفته و user_id آن را به یک پست نسبت می دهیم. سپس با استفاده از Faker داده های ساختگی را برای فیلدهای title و body پست ها ایجاد می کنیم.
بعد از اتمام کدهای مربوط به model factory حال باید با دستورات زیر کلاس های Database Seeder را ایجاد کنیم.
php artisan make:seeder UsersTableSeeder php artisan make:seeder PostsTableSeeder
فایل database/seeds/UserTableSeeder.php را باز کرده و کدهای مربوط به متد run() را ند زیر بروزرسانی کنید.
// database/seeds/UsersTableSeeder.php /** * Run the database seeds to create users. * * @return void */ public function run() { factory(App\User::class, 5)->create(); }
کد بالا باعث می شود بعد از اجرای کلاس های Seeder، پنج کاربر مختلف با داده های ساختگی ایجاد شود. همین کار را برای post هم انجام دهید. فایل database/seeds/PostsTableSeeder.php را باز کرده و کدهای متد run() را ند زیر بروزرسانی کنید.
// database/seeds/PostsTableSeeder.php /** * Run the database seeds to create posts. * * @return void */ public function run() { factory(App\Post::class, 10)->create(); }
کد بالا باعث می شود بعد از اجرای کلاس seeder، ده پست جدید با داده های ساختگی ایجاد شود.
قبل اجرای Database Seeder باید کد فایل database/seeds/DatabaseSeeder.php را ند زیر بروزرسانی کنید.
// database/seeds/DatabaseSeeder.php /** * Run the database seeds. * * @return void */ public function run() { $this->call(UsersTableSeeder::class); $this->call(PostsTableSeeder::class); }
حال می توانیم Database Seeder ها را ایجاد کنیم.
php artisan db:seed
با اجرای کد فوق، یک سری کدهای ساختگی در پایگاه داده شما ساخته می شود.
قبل از اینکه یک کاربر بتواند یک پست را favorite نماید، ابتدا باید به سیستم لاگین کند. برای اینکار از دستور make:auth برای ساخت سیستم احراز هویت استفاده می کنیم.
php artisan make:auth
با اجرای کد بالا تمام روت و ویوهایی که برای احراز هویت نیاز است، ساخته می شود.
در این مرحله روت های مورد نیاز برای برنامه را تعریف می کنیم. فایل routes/web.php را باز کرده و آن را مطابق با کدهای زیر بروزرسانی کنید.
// routes/web.php Auth::routes(); Route::get('/', 'PostsController@index'); Route::post('favorite/{post}', 'PostsController@favoritePost'); Route::post('unfavorite/{post}', 'PostsController@unFavoritePost'); Route::get('my_favorites', 'UsersController@myFavorites')->middleware('auth');
روت های Auth زی ساخته می شوند که ما از دستور make:auth استفاده کنیم.
یک روت به صفحه خانگی که تمام پست ها را نمایش می دهد، دو روت بعدی برای favorite کردن و یا از حالت favorite خارج کردن یک پست استفاده می شود. در انتها یک روت برای تمام پست های که یک کاربر favorite کرده، تعریف کردیم. این روت تنها برای کاربران احراز هویت شده قابل دسترسی است.
هنگامی که یک کاربر ثبت نام و یا لاگین کند، لاراول آن کاربر را به صفحه /home هدایت می کند. حال باید پروپرتی redirectTo را در فایل app/Http/Controllers/Auth/LoginController.php و app/Http/Controllers/Auth/RegisterController.php مطابق زیر بروزرسانی می کنیم.
protected $redirectTo = '/';
چون یک کاربر می تواند چندین پست را favorite کرده و یک پست هم می تواند توسط چندین کاربر favorite شود، رابطه بین کاربران و پست های favorite شده، چند به چند خواهد بود.
برای تعریف این رابطه، مدل User را باز کرده و کد زیر را به آن اضافه کنید.
// app/User.php /** * Get all of favorite posts for the user. */ public function favorites() { return $this->belongsToMany(Post::class, 'favorites', 'user_id', 'post_id')->withTimeStamps(); }
لاراول فرض می کند که جدول pivot ،post_user است، اما چون ما یک نام دیگر برای جدول pivot انتخاب کرده بودیم (favorite)، باید چند آرگومان اضافی هم به آن پاس بدهیم.
دقت داشته باشید که متد withTimeStamps() را به صورت زنجیره ای روی متد belongsToMany() استفاده کردیم. اینکار باعث می شود هر باری که سطر جدیدی درج و یا بروزرسانی شود، مقدار ستون timestamp (یعنی ستون های create_at و update_at ) روی جدول pivot تحت تاثیر قرار بگیرند.
حال یک کنترلر برای مدیریت نمایش پست ها، Favorite کردن یک پست و از حالت Favorite خارج کردن یک پست، ایجاد می کنیم.
php artisan make:controller PostsController
app/Http/Controllers/PostController.php را باز کرده و کد زیر را به آن اضافه کنید.
// app/Http/Controllers/PostsController.php // remember to use the Post model use App\Post; /** * Display a paginated list of posts. * * @return Response */ public function index() { $posts = Post::paginate(5); return view('posts.index', compact('posts')); }
در متد index() تمام پست ها را دریافت کرده و آنها را بصورت صفحه بندی درآورده و در هر صفحه 5 پست را نمایش می دهیم. سپس فایل ویو (که بعداً آن را ایجاد میکنیم) همراه با پست های دریافت شده، رندر می کنیم و به این ترتیب پست ها را نمایش می دهیم.
دقت کنید، هنگامی که از دستور make:auth استفاده کنیم، لاراول یک سری ویوهایی را برای ایجاد می کند.
حال ما فایل resourses/views/layouts/app.blade.php را باز کرده و یک سری تغییراتی را در آن اعمال می کنیم.
کد زیر را بعد از تگ <title> قرار دهید.
/ resources/views/layouts/app.blade.php <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
سپس کد زیر را قبل از قسمت لیست آیتم logout اضافه کنید.
// resources/views/layouts/app.blade.php <li> <a href="{{ url('my_favorites') }}">My Favorites</a> </li>
حال ویوی index را ایجاد میکنیم. یک فولدر به نام posts در فولدر views بوجود آورده و داخل آن یک فایل با نام index.blade.php ایجاد کنید. کدهای زیر را درون این فایل قرار دهید.
// resources/views/posts/index.blade.php @extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="page-header"> <h3>All Posts</h3> </div> @forelse ($posts as $post) <div class="panel panel-default"> <div class="panel-heading"> {{ $post->title }} </div> <div class="panel-body"> {{ $post->body }} </div> </div> @empty <p>No post created.</p> @endforelse {{ $posts->links() }} </div> </div> </div> @endsection
کد فوق باعث می شود، پست های به صورت صفحه بندی شده نمایش داده شود.
حال به postsController برگشته و یک متد برای مدیریت favorite کردن پست ها اضافه می کنیم.
کد زیر را به postController اضافه می کنیم.
// app/Http/Controllers/PostsController.php // remember to use use Illuminate\Support\Facades\Auth; /** * Favorite a particular post * * @param Post $post * @return Response */ public function favoritePost(Post $post) { Auth::user()->favorites()->attach($post->id); return back(); } /** * Unfavorite a particular post * * @param Post $post * @return Response */ public function unFavoritePost(Post $post) { Auth::user()->favorites()->detach($post->id); return back(); }
متد favoritePost() یک پست را به عنوان آرگومان می گیرد. با استفاده از رابطه favorites که در بالا تعریف کردیم، postID را به ID کاربر احراز هویت شده، متصل کرده، سپس آن را در جدول favorites درج میکنیم.
متد unFavoritePost() برعکس favoritePost() عمل می کند. به این صورت که ID کاربر احراز هویت شده را که به ID پست متصل شده، از جدول favorite حذف می کند.
در این قسمت سیستم لایک و علاقه مندی لاراول با را با vue یکپارچه و دکمه favorite را توسط یک کامپوننت vue ایجاد می کنیم. همچنین می توانیم از این کامپوننت در قسمت های مختلف برنامه از آن استفاده کنیم.
هنگامی که دکمه Favorite کلیک شد، بدون رفرش صفحه می توانیم یک پست را favorite کرده یا از حالت favorite خارج کنیم. برای اینکار از Axios که یک کلاینت Http مبتنی بر promise برای مرورگر و node.js است، استفاده می کنیم.
یک فایل با نام Favorite.vue در مسیر resources/assets/js/components ایجاد کرده و کدهای زیر را در آن قرار دهید.
// resources/assets/js/components/Favorite.vue <template> <span> <a href="#" v-if="isFavorited" @click.prevent="unFavorite(post)"> <i class="fa fa-heart"></i> </a> <a href="#" v-else @click.prevent="favorite(post)"> <i class="fa fa-heart-o"></i> </a> </span> </template> <script> export default { props: ['post', 'favorited'], data: function() { return { isFavorited: '', } }, mounted() { this.isFavorited = this.isFavorite ? true : false; }, computed: { isFavorite() { return this.favorited; }, }, methods: { favorite(post) { axios.post('/favorite/'+post) .then(response => this.isFavorited = true) .catch(response => console.log(response.data)); }, unFavorite(post) { axios.post('/unfavorite/'+post) .then(response => this.isFavorited = false) .catch(response => console.log(response.data)); } } } </script>
کامپوننت Favorite دو بخش دارد: template و Script.
هنگام استفاده از کامپوننت، کدهای موجود در بخش template رندر می شوند، همچنین از یک دستور شرطی برای نمایش دکمه مناسب استفاده می کنیم. طبق این شرط، اگر isFavorited برابر true بود، مقدار دکمه باید برابر Favorite شود و با کلیک روی دکمه باید متد unFavorite() اجرا شود.
در غیر اینصورت مقدار دکمه برابر unFavorite شده و با کلیک روی آن، متد unFavorite() اجرا می شود.
حال در بخش script تعدادی پروپرتی به نام های post (که برابر ID پست است) و favorited (بسته به اینکه پست توسط کاربر احراز هویت شده favorite شده باشد یا نه، مقدار true یا False می گیرد)، و isFavorited که برای استفاده در دستور شرطی از آن استفاده می کنیم، تعریف می نمایم.
هنگامی که کامپوننت اجرا شد، باید مقدار isFavorited را برابر مقدار پروپرتی isFavorite قرار دهیم. سپس پروپرتی isFavorite یک مقدار true یا false بر می گرداند.
در انتها دو متد به نام های favorite() و unfavorite() تعریف کردیم، که هر دوی این متدها یک پروپرتی post به عنوان آرگومان دریافت می کنند.
با استفاده از Axios یک درخواست post به روتی که قبلاً تعریف کرده بودیم، ارسال می کنیم. در متد Favorite() بعد از ارسال موفقیت آمیز درخواست post، مقدار isFavorited را برابر true قرار می دهیم و در غیر اینصورت خطاها را در کنسول نمایش می دهیم.
همین کارها را برای متد unFavorite() هم انجام می دهیم. با این تفاوت که مقدار isFavorited را برابر False قرار می دهیم.
قبل از اینکه بتوانیم از کامپوننت Favorite استفاده کنیم باید آن را در نمونه vue، ثبت کنیم. برای اینکار فایل resource/assets/js/app.js باز کرده و همان طور که می بینید لاراول یک کامپوننت Example را در این فایل ثبت کرده است. حال ما باید آن را با کامپوننت Favorite عوض کنیم.
// resources/assets/js/app.js Vue.component('favorite', require('./components/Favorite.vue'));
حال با دستور زیر استایل ها و اسکریپت های برنامه را کامپایل می کنیم.
npm run dev
حالا می توانیم از کامپوننت Favorite استفاده کنیم. فایل resources/views/posts/index.blade.php را باز کرده و کد زیر را بعد از تگ بسته div قسمت panel-body اضافه کنید.
// resources/views/posts/index.blade.php @if (Auth::check()) <div class="panel-footer"> <favorite :post={{ $post->id }} :favorited={{ $post->favorited() ? 'true' : 'false' }} ></favorite> </div> @endif
دکمه Favorite فقط به کاربران احراز هویت شده نمایش داده می شود.
از طرفی پروپرتی هایی که هنگام ساخت کامپوننت تعریف کرده بودیم را به کامپوننت Favorite ارسال می کنیم و از این طریق می توانیم بفهمیم که اگر پستی توسط یک کاربر احراز هویت شده Favorite شده بود، باید متد favorited() را روی آن پست فراخوانی کنیم.
برای تعریف متد Favorited() فایل app/Post.php را باز کرده و کد زیر را به آن اضافه کنید.
// app/Post.php // remember to use use App\Favorite; use Illuminate\Support\Facades\Auth; /** * Determine whether a post has been marked as favorite by a user. * * @return boolean */ public function favorited() { return (bool) Favorite::where('user_id', Auth::id()) ->where('post_id', $this->id) ->first(); }
کد فوق، اولین نتیجه ای که user_id برابر id کاربر احراز هویت شده بود و post_id برابر id پستی که این متد روی آن فراخوانی شده بود، را گرفته و تبدیل به یک مقدار بولین می کند.
نتیجه اجرای این آموزش در مرورگر مطابق تصویر زیر است
در این مرحله یک روت با نام my_favorited تعریف می کنیم. این روت تنها برای کاربران احراز هویت شده قابل دسترسی است و توسط این روت کاربران پست هایی که Favorite کرده اند را می توانند مشاهد کنند.
در زیر یک کنترلر به نام UsersController برای مدیریت این روت ایجاد می کنیم.
php artisan make:controller UsersController
فایل app/Http/Controllers/UsersController.php را باز کرده و کدهای زیر را به آن اضافه کنید
// app/Http/Controllers/UsersController.php // remember to use use Illuminate\Support\Facades\Auth; /** * Get all favorite posts by user * * @return Response */ public function myFavorites() { $myFavorites = Auth::user()->favorites; return view('users.my_favorites', compact('myFavorites')); }
متد myFavorite() از رابطه favorites که قبلاً تعریف کرده بودیم استفاده می کند.
این متد تمام پست هایی که یک کاربر احراز هویت شده Favorite کرده را بر می گرداند.
سپس یک ویو برای نمایش پست های Favorite شده، بر می گردانیم.
حال باید View را ایجاد کنیم. یک فولدر به نام Users در فولدر resources/views ایجاد کنید و داخل فولدر users یک ویو با نام my_favorites.blade.php ایجاد کنید و کدهای زیر را در آن قرار دهید.
// resources/views/users/my_favorites.blade.php @extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="page-header"> <h3>My Favorites</h3> </div> @forelse ($myFavorites as $myFavorite) <div class="panel panel-default"> <div class="panel-heading"> {{ $myFavorite->title }} </div> <div class="panel-body"> {{ $myFavorite->body }} </div> @if (Auth::check()) <div class="panel-footer"> <favorite :post={{ $myFavorite->id }} :favorited={{ $myFavorite->favorited() ? 'true' : 'false' }} ></favorite> </div> @endif </div> @empty <p>You have no favorite posts.</p> @endforelse </div> </div> </div> @endsection
کد فوق شبیه ویوی index.blade.php است. همانطور که می بینید از کامپوننت Favorite هم استفاده کردیم.
بسیار عالی دوستان عزیز. این آموزش به اتمام رسید امیدوارم با الگوها و الگوریتم های ساخت سیستم لایک و علاقه مندی لاراول آشنایی کافی را پیدا کرده باشید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.