در این آموزش قصد داریم نحوه انجام عملیات crud با vue در لاراول را به شما آموزش دهیم. لاراول یکی از فریم ورک های محبوب PHP است که سرعت رشد، مقیاس پذیری و انعطاف پذیری بالایی را دارا می باشد.
Vue.js یکی از کتابخانه های جاوا اسکریپت است که به سرعت در حال رشد است و محبوبیت بسیاری در بین توسعه دهندگان front end دارد. فریمورک لاراول بصورت پیش فرض از کتابخانه Vue.js پشتیبانی به عمل می آورد. در این مقاله یک پروژه جداگانه برای بخش front end مان ایجاد نمی کنیم، چون لاراول بصورت پیش فرض از Vue.js پشتیبانی می کند.
دوستان عزیز آکادمی آنلاین روکسو در حال حاضر دوره آموزشی ویو جی اس را به صورت کامل از صفر تا صد و پروژه محور برگزار کرده است که می توانید به صورت آنلاین در آن شرکت کرده و تخصص کافی را برای استفاده از این فریم ورک بدست آورید.
بنابراین کامپوننت های Vue را داخل همان فولدر های لاراول ایجاد می کنیم.
در این پروژه با استفاده از لاراول و vue.js یک برنامه تک صفحه ای یا Single page Application یا SPA را ایجاد می کنیم. کاربران در این برنامه می توانند اقدام به ارسال پست جدید، ویرایش، مشاهده و حذف پست ها بکنند.
برای بخش back end این پروژه از Api های لاراول استفاده می کنیم.
برای شروع کار، ابتدا باید فریمورک لاراول را نصب کنیم. برای اینکار ترمینال را باز کرده و دستورات زیر را در آن اجرا کنید.
laravel new vuelaravelcrud
حال به مسیر پروژه رفته و دستور زیر را برای نصب وابستگی های بخش front-end برنامه، اجرا کنید.
npm install
حال با دستور زیر برنامه را در ویرایشگر خودتان باز کنید. من در این جا از visual studio code استفاده می کنم.
code .
برای تنظیم پیکربندی مربوط به پایگاه داده برنامه، کدهای زیر را در فایل .env قرار دهید.
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=vuecrud DB_USERNAME=root DB_PASSWORD=root
فایل را ذخیره کنید. حال می توانید با موفقیت به پایگاه داده MySQL متصل شوید.
حال با اجرای دستور زیر، asset های برنامه را کامپایل کنید.
npm run dev
همچنین با اجرای دستور زیر، هر کدی که به asset های قبلی اضافه کرده و یا اگر کدهای قبلی را ویرایش کنید، به صورت آنی کدها کامپایل خواهند شد.
npm run watch
برای نصب vue-router و vue-axios دستورات زیر را اجرا کنید.
Vue-router برای مسیریابی کامپوننت های مختلفی که در یک برنامه vue.js نوشته اید، استفاده می شود و vue-axios برای ارسال درخواست به سرور.
npm install vue-router vue-axios --save
حال باید فایل App.js که در مسیر resource/js قرار دارد را مطابق زیر ویرایش کنید.
// App.js require('./bootstrap'); window.Vue = require('vue'); import VueRouter from 'vue-router'; Vue.use(VueRouter); import VueAxios from 'vue-axios'; import axios from 'axios'; Vue.use(VueAxios, axios); Vue.component('example-component', require('./components/ExampleComponent.vue')); const router = new VueRouter({ mode: 'history'}); const app = new Vue(Vue.util.extend({ router })).$mount('#app');
حال یک فایل با نام post.blade.php در فولدر resource/views ایجاد کنید و کدهای زیر را در آن قرار دهید.
<!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Laravel</title> <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css"> <link href="{{ mix('css/app.css') }}" type="text/css" rel="stylesheet" /> <meta name="csrf-token" value="{{ csrf_token() }}" /> </head> <body> <div id="app"> <example-component></example-component> </div> <script src="{{ mix('js/app.js') }}" type="text/javascript"></script> </body> </html>
حال باید روت های برنامه را در فایل web.php بنویسید. در این مقاله ما یک برنامه تک صفحه ای با لاراول و vue.js ایجاد می کنیم، بنابراین باید روت های زیر را تعریف کنیم تا بتوانیم هر آدرسی که به آن ارسال کردیم را به یک مسیر درست هدایت کنیم. در غیر اینصورت خظای 404 را دریافت می کنیم، چون در لاراول هیچ روتی تعریف نکرده ایم و تنها برای کامپوننت های vue برنامه مان روت تعریف کردیم.
با کد زیر می توانید از روت های لاراول و Vuejs به عنوان روت های vue استفاده کنید و همچنین می توانید بسته به url جاری، کامپوننت های مناسب vue را نمایش دهید.
<?php Route::get('/{any}', function () { return view('post'); })->where('any', '.*');
فایل را ذخیره کرده و نتیجه را در مرورگر ببینید. همان طور که می بینید کامپوننت های Vue به درستی با فریمورک لاراول یکپارچه شده اند.
یک فولدر به نام components در مسیر resources/js ایجاد کرده و فایل های زیر را در آن بوجود بیاورید.
// HomeComponent.vue <template> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card card-default"> <div class="card-header">Home Component</div> <div class="card-body"> I'm the Home Component component. </div> </div> </div> </div> </template> <script> export default { mounted() { console.log('Component mounted.') } } </script>
// CreateComponent.vue <template> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card card-default"> <div class="card-header">Create Component</div> <div class="card-body"> I'm the Create Component component. </div> </div> </div> </div> </template> <script> export default { mounted() { console.log('Component mounted.') } } </script>
// EditComponent.vue <template> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card card-default"> <div class="card-header">Edit Component</div> <div class="card-body"> I'm an Edit component. </div> </div> </div> </div> </template> <script> export default { mounted() { console.log('Example Component mounted.') } } </script>
// IndexComponent.vue <template> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card card-default"> <div class="card-header">Index Component</div> <div class="card-body"> I'm an Index component. </div> </div> </div> </div> </template> <script> export default { mounted() { console.log('Index Component mounted.') } } </script>
کدهای زیر را داخل فایل app.js قرار دهید.
// app.js require('./bootstrap'); window.Vue = require('vue'); import VueRouter from 'vue-router'; Vue.use(VueRouter); import VueAxios from 'vue-axios'; import axios from 'axios'; import App from './App.vue'; Vue.use(VueAxios, axios); import HomeComponent from './components/HomeComponent.vue'; import CreateComponent from './components/CreateComponent.vue'; import IndexComponent from './components/IndexComponent.vue'; import EditComponent from './components/EditComponent.vue'; const routes = [ { name: 'home', path: '/', component: HomeComponent }, { name: 'create', path: '/create', component: CreateComponent }, { name: 'posts', path: '/posts', component: IndexComponent }, { name: 'edit', path: '/edit/:id', component: EditComponent } ]; const router = new VueRouter({ mode: 'history', routes: routes}); const app = new Vue(Vue.util.extend({ router }, App)).$mount('#app');
در بالا چهار کامپونت قبلی را import کرده و همچنین برای برنامه روت تعریف کردیم. سپس یک آبجکت router ایجاد کرده و آن را به برنامه vue ارسال کردیم.
حال یک کامپوننت دیگر به نام App.vue در مسیر resources/js ایجاد کرده و کدهای زیر را به آن اضافه کنید.
// App.vue <template> <div class="container"> <div> <transition name="fade"> <router-view></router-view> </transition> </div> </div> </template> <style> .fade-enter-active, .fade-leave-active { transition: opacity .5s } .fade-enter, .fade-leave-active { opacity: 0 } </style> <script> export default{ } </script>
در بالا ما ویوی مربوط به router را ایجاد کردیم. کدهای فوق بسته به url وارد شده در مرورگر، کامپوننت مناسب را نمایش می دهند. یعنی اگر آدرس /create وارد مرورگر شود، آنگاه کامپوننت CreateComponent نمایش داده می شود.
کدهای زیر را در فایل App.vue بنویسید. با کدهای زیر، منوهای پیمایشی برنامه را ایجاد می کنم.
// App.vue <template> <div class="container"> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <ul class="navbar-nav"> <li class="nav-item"> <router-link to="/" class="nav-link">Home</router-link> </li> <li class="nav-item"> <router-link to="/create" class="nav-link">Create Post</router-link> </li> <li class="nav-item"> <router-link to="/posts" class="nav-link">Posts</router-link> </li> </ul> </nav><br /> <transition name="fade"> <router-view></router-view> </transition> </div> </template> <style> .fade-enter-active, .fade-leave-active { transition: opacity .5s } .fade-enter, .fade-leave-active { opacity: 0 } </style> <script> export default{ } </script>
فایل را ذخیره کرده و نتیجه را در خروجی بینید.
فایل CreateComponent.vue را باز کرده و کدهای زیر را در آن قرار دهید.در زیر از یک فرم بوت استرپ برای ایجاد یک پست جدید استفاده می کنیم.
// CreatePost.vue <template> <div> <h1>Create A Post</h1> <form @submit.prevent="addPost"> <div class="row"> <div class="col-md-6"> <div class="form-group"> <label>Post Title:</label> <input type="text" class="form-control" v-model="post.title"> </div> </div> </div> <div class="row"> <div class="col-md-6"> <div class="form-group"> <label>Post Body:</label> <textarea class="form-control" v-model="post.body" rows="5"></textarea> </div> </div> </div><br /> <div class="form-group"> <button class="btn btn-primary">Create</button> </div> </form> </div> </template> <script> export default { data(){ return { post:{} } }, methods: { addPost(){ console.log(this.post); } } } </script>
همان طور که در کدهای فوق می بینید، ما دو فیلد داریم: عنوان و محتوای پست.
همچنین یک متد با نام addPost() تعریف کردیم. بنابراین هنگامی که کاربر فرمی را Submit کند، ما مقادیر فیلدهای ورودی را به متد addPost() ارسال می کنیم.
سپس داده ها را توسط یک متد post به سرور لاراول ارسال کرده و لاراول داده ها را در پایگاه داده ذخیره می کند.
فایل را ذخیره کرده و آدرس زیر را در مرورگر وارد کنید. localhost:3000/create.
به این ترتیب وارد صفحه ای مطابق تصویر زیر می شوید.
هدف اصلی فریم ورک لاراول در این مثال، ساخت api برای back-end پروژه است. برای این منظور یک مدل به نام post به همراه migration مربوط به آن ایجاد می کنیم.
php artisan make:model Post -m
حال کدهای زیر را در فایل [timestamp]_create_posts_table.php
قرار دهید.
public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->text('body'); $table->timestamps(); }); }
سپس پایگاه داده را با دستور زیر migrate کنید.
php artisan migrate
سپس برای جلوگیری از بروز خطای mass assignment کدهای زیر را در مدل post.php قرار دهید.
<?php // Post.php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { protected $fillable = ['title', 'body']; }
همچنین با دستور زیر یک کنترلر ایجاد کنید.
php artisan make:controller PostController
برای توسعه Api از resource collection های لاراول استفاده می کنیم. پس ابتدا یک resource ایجاد می کنیم.
php artisan make:resource PostCollection
هنگام ساخت یک api شما به یک لایه انتقال برای قرار گرفتن بین مدل های Eloquent و پاسخ های json برگشت داده شده به کاربر، نیاز دارید.
کلاس های resource لاراول به شما اجازه می دهند تا بتوانید به سرعت از مدل های تان خروجی json بگیرید.
resource postCollection ایی که در بالا ایجاد کردیم، در مسیر app/Http/Resources/postCollection.php قرار می گیرد.
<?php // PostCollection.php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class PostCollection extends ResourceCollection { /** * Transform the resource collection into an array. * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return parent::toArray($request); } }
ابتدا یک متد برای ذخیره داده ها در پایگاه داده MySQL ایجاد می کنیم.
<?php // PostController.php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Resources\PostCollection; use App\Post; class PostController extends Controller { public function store(Request $request) { $post = new Post([ 'title' => $request->get('title'), 'body' => $request->get('body') ]); $post->save(); return response()->json('success'); } }
حال توابع edit ،update ،index و delete را هم تعریف می کنیم.
<?php // PostController.php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Resources\PostCollection; use App\Post; class PostController extends Controller { public function store(Request $request) { $post = new Post([ 'title' => $request->get('title'), 'body' => $request->get('body') ]); $post->save(); return response()->json('successfully added'); } public function index() { return new PostCollection(Post::all()); } public function edit($id) { $post = Post::find($id); return response()->json($post); } public function update($id, Request $request) { $post = Post::find($id); $post->update($request->all()); return response()->json('successfully updated'); } public function delete($id) { $post = Post::find($id); $post->delete(); return response()->json('successfully deleted'); } }
حال باید روت های مورد نیاز برنامه را در فایل routes/api.php ایجاد کنیم.
<?php // api.php use Illuminate\Http\Request; Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); Route::post('/post/create', 'PostController@store'); Route::get('/post/edit/{id}', 'PostController@edit'); Route::post('/post/update/{id}', 'PostController@update'); Route::delete('/post/delete/{id}', 'PostController@delete'); Route::get('/posts', 'PostController@index');
تا به اینجا بخش back-end برنامه را ایجاد کردیم.
قدم بعد ارسال یک درخواست post به سرور لاراول است. فایل CreateComponent.php را باز کرده و کدهای زیر را در متد addPost قرار دهید.
// CreateComponent.vue addPost(){ let uri = 'http://vuelaravelcrud.test/api/post/create'; this.axios.post(uri, this.post).then((response) => { this.$router.push({name: 'posts'}); }); }
در بالا یک درخواست post به سرور ارسال کردیم و سرور داده ها را در پایگاه داده ذخیره کرد. حال می خواهیم قابلیت نمایش پست ها را پیاده سازی کنیم. برای این منظور فایل IndexComponent.vue را مانند زیر بروزرسانی کنید.
// IndexComponent.vue <template> <div> <h1>Posts</h1> <div class="row"> <div class="col-md-10"></div> <div class="col-md-2"> <router-link :to="{ name: 'create' }" class="btn btn-primary">Create Post</router-link> </div> </div><br /> <table class="table table-hover"> <thead> <tr> <th>ID</th> <th>Item Name</th> <th>Item Price</th> <th>Actions</th> </tr> </thead> <tbody> <tr v-for="post in posts" :key="post.id"> <td>{{ post.id }}</td> <td>{{ post.title }}</td> <td>{{ post.body }}</td> <td><router-link :to="{name: 'edit', params: { id: post.id }}" class="btn btn-primary">Edit</router-link></td> <td><button class="btn btn-danger">Delete</button></td> </tr> </tbody> </table> </div> </template> <script> export default { data() { return { posts: [] } }, created() { let uri = 'http://vuelaravelcrud.test/api/posts'; this.axios.get(uri).then(response => { this.posts = response.data.data; }); } } </script>
در بالا هنگامی که کامپوننت ساخته شد، یک درخواست برای بازیابی داده ها ارسال می کنیم.
Axios به طور پیش فرض داده های پست شده به back-end را داخل data می ریزد. سپس از این data به عنوان کلید resource ایی که ساختیم استفاده می کنیم. بنابراین برای دریافت داده های واقعی باید از response.data.data
استفاده کنیم. اگر از axios استفاده نکنید، باید تنها از response.data استفاده کرد.
حال هر گاه کامپوننت مربوط به ویرایش بارگزاری شد، باید داده ها را از سرور برای نمایش به کاربر بازیابی کنیم.
سپس بعد از تغییر داده ها در textbox و textarea و زدن دکمه update، متد updatePost() را فراخوانی کرده و یک درخواست post به سرور ارسال و داده ها را بروزرسانی می کنیم.
// EditComponent.vue <template> <div> <h1>Edit Post</h1> <form @submit.prevent="updatePost"> <div class="row"> <div class="col-md-6"> <div class="form-group"> <label>Post Title:</label> <input type="text" class="form-control" v-model="post.title"> </div> </div> </div> <div class="row"> <div class="col-md-6"> <div class="form-group"> <label>Post Body:</label> <textarea class="form-control" v-model="post.body" rows="5"></textarea> </div> </div> </div><br /> <div class="form-group"> <button class="btn btn-primary">Update</button> </div> </form> </div> </template> <script> export default { data() { return { post: {} } }, created() { let uri = `http://vuelaravelcrud.test/api/post/edit/${this.$route.params.id}`; this.axios.get(uri).then((response) => { this.post = response.data; }); }, methods: { updatePost() { let uri = `http://vuelaravelcrud.test/api/post/update/${this.$route.params.id}`; this.axios.post(uri, this.post).then((response) => { this.$router.push({name: 'posts'}); }); } } } </script>
حال می خواهیم قابلیت حذف داده ها را پیاده سازی کنیم.
برای اینکار کدهای زیر را در فایل IndexComponent.vue قرار دهید.
// IndexComponent.vue <template> <div> <h1>Posts</h1> <div class="row"> <div class="col-md-10"></div> <div class="col-md-2"> <router-link :to="{ name: 'create' }" class="btn btn-primary">Create Post</router-link> </div> </div><br /> <table class="table table-hover"> <thead> <tr> <th>ID</th> <th>Item Name</th> <th>Item Price</th> <th>Actions</th> </tr> </thead> <tbody> <tr v-for="post in posts" :key="post.id"> <td>{{ post.id }}</td> <td>{{ post.title }}</td> <td>{{ post.body }}</td> <td><router-link :to="{name: 'edit', params: { id: post.id }}" class="btn btn-primary">Edit</router-link></td> <td><button class="btn btn-danger" @click.prevent="deletePost(post.id)">Delete</button></td> </tr> </tbody> </table> </div> </template> <script> export default { data() { return { posts: [] } }, created() { let uri = 'http://vuelaravelcrud.test/api/posts'; this.axios.get(uri).then(response => { this.posts = response.data.data; }); }, methods: { deletePost(id) { let uri = `http://vuelaravelcrud.test/api/post/delete/${id}`; this.axios.delete(uri).then(response => { this.posts.splice(this.posts.indexOf(id), 1); }); } } } </script>
در بالا توسط رویداد click در vue ، id پست جاری را گرفته و پستی که آن id دارد را از پایگاه داده حذف می کنیم. همچنین توسط متد splice آن داده ها را از آرایه سمت کلاینت هم حذف می کنیم.
به این ترتیب آموزش مان به پایان رسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.