رتبه موضوع:
  • 4 رای - 5 میانگین
  • 1
  • 2
  • 3
  • 4
  • 5
آموزش جامع Laravel
#1
آموزش جامع فریمورک Laravel

   
Laravel  یکی از محبوب ترین فریمورک های PHP در بین برنامه نویسان است که برای توسعه برنامه های تحت وب در نظر گرفته شده است. من در این تاپیک قصد دارم این فریمورک را با  زبانی ساده و با مثال های کاربردی به زبان فارسی آموزش بدهم و امیدوارم که برایتان مفید واقع شود.

نکته: به‌مرور با توجه به تغییرات جدید در نسخه‌های بعدی لاراول پست‌ها را با تغییرات جدید به‌روز خواهم کرد.

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

لینک سوپرگروه پرسش و پاسخ مرتبط به تاپیک در تلگرام

در همین پست اول فهرست آموزش هارا به صورت لینک قرار خواهم داد.

فهرست مطالب
مقدمه ای بر لاراول
نصب و پیکربندی
routing
کار با view و Blade
کار با controller
کار با Middleware ها
Request و Response
مقدمات کار با دیتابیس
 Eloquent ORM و بازیابی داده ها
Eloquent ORM و درج و به روزرسانی و حذف
Migration
Relationships در Eloquent
Validation
افزودن کلاس های Html و Form
Authentication
مطالب تکمیلی Authentication
Authorization
کار با session ها
ارسال ایمیل
صفحه بندی یا pagination
کار با AJAX
reset کردن کلمه عبور کاربران
کار با captcha
Task Scheduling
تعریف یک Artisan Console Command
آپلود فایل
یک نکته امنیتی در مورد آپلود فایل
چند نکته امنیتی در لاراول
چندزبانه کردن برنامه و استفاده از Command Bus
Accessor و Mutator ها در Eloquent
Authorization و کار با کلاس های Policy
کار با Elixir
کار با Seeder و Model Factory
Relationships - رابطه Many To Many (چند به چند)
پیاده سازی دسته بندی چند سطحی و نمایش آن به صورت بازگشتی در ویو Blade
احرازهویت چندگانه یا Multi Auth
ارسال ایمیل با Mailable
کار با Event و Listener
ثبت نام کاربر با تایید ایمیل
کار با Cache
کار با Laravel Mix
کار با  Notification  ها
component و slot در Blade
احرازهویت توسط شبکه های اجتماعی با Socialite


فایل‌های پیوست تصاویر بندانگشتی
   
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
#2
مقدمه ای بر لاراول
لاراول با اینکه یک فریمورک جوانی هست امایکی از محبوب ترین فریمورک های PHP در بین برنامه نویسان است که این محبوبیت خودش رو به خاطر یادگیری سریع و آسان و راحتی استفاده به دست آورده است. از مزایایی که این فریمورک داره دارای یک syntax زیبا و گویا هست و با نگاه کردن به کد میتونید متوجه بشید که میخواد چه کاری رو انجام بده. همچنین این فریمورک دارای منابع آموزشی بسیار زیادی چه به صورت کتاب الکترونیکی و چه به صورت آنلاین و فروم می باشد که فروم laracasts معروفترین اونها هست که شما هم میتونید جواب خیلی از سوالات خود را در این فروم پیدا کنید یا اینکه با عضویت در آن بپرسید. لاراول هدفش این بوده که فرآیند توسعه را برای توسعه دهنده لذت بخش بکند و از ویژگی های فریمورک های مطرح سایر زبان ها مانند Ruby on Rails و ASP.NET و Sinatra هم استفاده کرده است.

آخرین نسخه لاراول تا زمان نوشتن این پست نسخه 5.4 هست که نیازمند ورژن PHP نسخه 5.6.4 یا بیشتر می باشد و همچنین باید extension های PHP زیر نیز روی سرور شما فعال باشد:
  • OpenSSL PHP Extension
  • PDO PHP Extension
  • Mbstring PHP Extension
  • Tokenizer PHP Extension
  • XML PHP Extension

قبل از اینکه بخواهید لاراول رو یاد بگیرید حتما به زبان برنامه نویسی PHP و مباحث شی گرایی در PHP مانند interface ها و namespace بیشتر آشنا شوید و نحوه کار با Closure ها تسلط داشته باشید. همچنین با الگوهای طراحی مختلف که مهمترینش الگوی طراحی MVC آشنا باشید. همچنین به مفاهیم پایگاه داده و روابط بین جداول هم تسلط کافی داشته باشید.
در صورتی که می خواهید با جادوی لاراول در زمینه Front-End همچون کار با webpack و Sass یا Less و سایر موراد Laravel Mix نیز کار کنید برای کار با JavaScript نیازمند تسلط نسبی به این زبان و فریمورک Vue.js (به صورت پیش فرض در لاراول وجود دارد) یا Angular.js و همچنین ECMAScript 6 می باشید و همچنین برای CSS نیز با Sass یا Less آشنا باشید.

وبسایت رسمی این فریمورک هم http://laravel.com/ است. میتونید برای یادگیری و نحوه کار بخش های مختلف این فریمورک به بخش Documentation آن مراجعه کنید.

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



پاسخ
#3
نصب لاراول

قبل از اینکه بخواهیم لاراول رو نصب کنیم ابتدا باید بدانیم نسخه PHP سرورمان و همچنین یکسری extension های PHP روی آن نصب و لود شده باشند. برای نصب لاراول 5.4 باید نسخه PHP سرورتان 5.6.4 یا بیشتر باشد و همچنین extension های OpenSSL و PDO و Mbstring و Tokenizer  روی سرورتان لود شده باشد. اگر یکبار دستور ()phpinfo رو اجرا کنید می تونید به این اطلاعات در سرورتان دست پیدا کنید.

به دو روش می توانیم لاراول رو نصب کنیم که روش اول که معمولا اونهایی که Ruby کار هستند باهاش آشنایی دارند نصب از طریق installer لاراول هست و روش دوم که خودم هم از آن استفاده میکنم نصب با استفاده از دستور create-project خود composer هست. در صورتی که composer رو توی سیستم عامل خودتان ندارید اینجا مراجعه کنید و سپس با توجه به سیستم عاملی که استفاده میکنید آن را دانلود و نصب کنید. دوستانی که از ویندوز استفاده میکنند یک فایل exe وجود دارد که مثل برنامه های دیگر میتونید آن را دانلود و نصب کنید. البته ممکنه در هنگام نصب لاراول با composer با مشکلاتی مواجه شوید که آن به خاطر connection اینترنت شما هست که پیشنهاد میشه در صورت بروز این مشکلات از VPN استفاده کنید.

بعد اینکه compser رو نصب کردید اگر داخل محیط ترمینال لینوکس یا cmd ویندوز خودتان کلمه composer رو تایپ و اینتر بزنید باید یکسری اطلاعات در مورد composer و command های اون رو مشاهده کنید که در این صورت composer روی سیستم عامل شما به درستی نصب شده است.
توی همان ترمینال ابتدا به دایرکتوری یا پوشه ای که می خواهید لاراول رو در اونجا نصب کنید با دستور cd بروید مثلا در ویندوز و نرم افزار xampp به این صورت می تونیم به پوشه مورد نظرمان برویم:
cd c:\xampp\htdocs
با دستور زیر آخرین نسخه لاراول رو در پوشه مورد نظر نصب میکنید :
composer create-project --prefer-dist laravel/laravel project_name
نام فولدر پروژه را هم که لاراول داخل آن نصب خواهد شد را همانند مثال بالا که project_name قراردادم نامگزاری کنید و در صورتی که چیزی ننویسید به صورت پیش فرض laravel نامگزاری خواهد شد.
همچنین اگر می خواهید نسخه های خاصی را نصب کنید باید ورژن لاراول را در انتهای آن بیاورید :
composer create-project laravel/laravel project_name "5.1.*"
در مثال بالا نسخه 5.1 لاراول را نصب کردیم.

بعد اینکه لاراول رو نصب کردین اگر از سیستم عامل لینوکس استفاده می کنید باید مجوزهای فایل یا permission نوشتن رو به پوشه storage  و تمام زیر پوشه های آن و همچنین پوشه bootstrap/cache بدهید.

پیکربندی لاراول
تمامی تنطیمات مربوط به برنامه تان و فریمورک لاراول رو در پوشه Config میتونید ویرایش کنید مثلا در فایل app.php می تونید url برنامه رو ست کنید و همچنین timezone برنامه تان را به Asia/Tehran تغییر دهید. یکسری تنطیمات هم از فایل env. که در پوشه اصلی لاراول قرار داده شده با استفاده از تابع کمکی ()env گرفته می شوند و در صورتی که در آن فایل ست نشده بود پارامتر دومی که به این تابع پاس داده شده رو که پیش فرض هست رو استفاده میکند. به طور مثال debug به همین صورت عمل کرده است. debug اگر false باشد برنامه  مد production خواهد بود که مناسب برای زمان publish برنامه بر روی وب می باشد ولی اگر true باشد مد development هست و برای زمانی که در حال کدنویسی و توسعه برنامه هستید مناسب می باشد و تمامی exception ها و خطاهای رخ داده شده در حین برنامه نویسی را برایتان نمایش خواهد داد.
در صورتی که از composer برای نصب لاراول استفاده کرده باشد APP_KEY به طور خودکار ست می شود اما اگر بخواهید آن را تغییر دهید با فرمان زیر می توانید آن را تغییر دهید.
php artisan key:generate 
لاراول از این کلید برای رمزنگاری ها استفاده میکند.

برای اجرای لاراول در مرورگر می تونید به صورت سنتی با استفاده از url به صورت مثلا http://localhost/laravel/public آن را مشاهده کنید.این نکته رو در نظر داشته باشید که public پوشه root برنامه تان هست و تمامی درخواست ها از طریق فایل htaccess موجود در این پوشه به فایل index.php فرستاده می شود و آن هم فایل bootstrap.php رو لود میکند که همان پیاده سازی الگوی طراحی MVC است. همچنین می توانید با استفاده از دستور خط فرمان php artisan serve آدرس http://localhost:8000 رو باز کنید و اولین صفحه لاراول رو مشاهده کنید.

ساختار فایل ها و دایرکتوری ها
اگر فولدری  که لاراول را در آن نصب کرده اید باز کنید با فایل ها و دایرکتوری های زیر مواجه می شوید که خلاصه ای از آن را در زیر به همراه توضیحات مختصری آورده ام.
app : با آن در طول توسعه برنامه زیاد سروکار خواهیم داشت شامل کدهای برنامه مان از قبیل کنترلرها و مدلها و اغلب کلاس های برنامه ما در این فولدر قرار می گیرند.
bootstrap: در این فولدر فایل های راه اندازی فریمورک و autolaod  قرار دارند.
config : همانطور که از نامش مشخص است حاوی تمام فایلهای پیکربندی و تنظیمات برنامه است.
database: حاوی فایل های مربوط به migration و seed برنامه تان است. نگران نباشید در تاپیک مورد نظر با این دو اصطلاح بیشتر آشنا خواهید شد.
public: پوشه root برنامه است که تمامی درخواست ها را توسط فایل htaccess بازنویسی و به فایل index.php فرستاده می شوند. در این پوشه فایل های استاتیک برنامه مانند تصاویر و جاوااسکریپت و css را هم قرار می دهیم.
resources: در این فولدر فایل های مربوط به Sass و  Less در پوشه assets و همچنین view های برنامه در پوشه views و فایل های مربوط به زبان برنامه هم در پوشه lang قرار میگیرند.
routes: در این فولدر تمام route های برنامه که تعریف می کنیم را قرار می دهیم.
storage: در این فولدر فایل هایی که توسط فریمورک تولید می شوند قرار میگیرد. به طور مثال فایل های مربوط به cache یا log های برنامه و همچنین محل ذخیره سازی فایل های آپلود شده هم می تواند باشد.
tests: این پوشه شامل فایل هایی  برای تست برنامه می باشد. برای مثال PhpUnit که به صورت پیش فرض در لاراول می توانیم با آن کار کنیم فایل موردنظر برای تست را در این فولدر قرار می دهیم.
vendor: در این پوشه هم تمامی third-party های نصب شده توسط composer در آن قرار میگیرند.
همچنین از فایل های env. و composer.json هم زیاد در برنامه استفاده خواهیم کرد. در طول آموزش با نحوه کار هرکدام از آنها بیشتر آشنا خواهید شد.

در قسمت بعدی در مورد routing در لاراول آشنا خواهیم شد و با استفاده از یک مثال کاربردی مباحث رو جلو خواهیم برد.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
#4
Routing
در فولدر routes باید route های برنامه را تعریف کنیم. در فایل web.php تمام route هایی که مربوط به برنامه هست و مربوط به رابط وب برنامه هست و نیاز به مواردی مثل سشن ها و محافظت csrf و ... داریم را ثبت می کنم. همچنین route  های مربوط api ها را در api.php و کنسول را در console.php ثبت می کنیم که فعلا مورد بحث آموزش ما نیستند. اگر همین فایل را بازکنید یک route ثبت شده که url آن یک / است که همان صفحه homepage وبسایت می باشد و از طریق تابع بی نام یک فایل view را render کرده و نمایش می دهد. با استفاده از کلاس Facade Route می توانیم با توجه به درخواست Http ای که آمده مثلا get یا post است متدی همنام با آن را صدا زده و طبق مثال های زیر route را تعریف کنیم :
Route::get('/', function () {
   return 'Hello World';
});

Route::post('foo/bar', function () {
   return 'Hello World';
});

همانطور که مشاهده می کنید پارامتر اول مسیری است که در url می آید و پارامتر دوم هم یک تابع بی نام است که دستورات داخل آن اجرا می شود و در بحث کنترلرها در مورد route به یک کنترلر و اکشن خاص آشنا خواهیم شد.

اگر بخواهیم به مسیر پارامتر هم بدهیم کافی است نام پارامتر را داخل آکولاد قرار دهیم و در هنگام تولید url مقداری را به آن پاس می دهیم :
Route::get('user/{id}', function ($id) {
   return 'User '.$id;
});

خب برای اینکه مطلب طولانی نشود می تونید به مستندات خود لاراول مراجعه کنید و در آنجا با انواع و اقسام مثال ها و نوع های مختلف مسیردهی بیشتر آشنا شوید.

توی این سری آموزش ها بر خلاف آموزش هایی که در انجمن برنامه نویس داشتم میخوام بیشتر به صورت پروژه محور و کاربردی آموزش هامو پیش ببرم.ما می خواهیم یک پروژه خیلی ساده رو باهم انجام دهیم و به مرور آن را گسترش بدهیم.

فرض کنید یک وبسایت داریم که شامل صفحاتی به نام های  صفحه اصلی و درباره ما و تماس با ما می باشد. فایل routes/web.php را باز میکنیم و مسیرها را به صورت زیر ثبت میکنیم :
Route::get('/', function()
{
   return 'سلام به اولین برنامه من در لاراول خوش آمدید!';
});

Route::get('/about', function()
{
   return 'این صفحه درباره ما می باشد';
});

Route::get('/contact', function()
{
   return 'این صفحه تماس با ما می باشد';
});

حالا اگر url های http://localhost:8000/ و http://localhost:8000/about و http://localhost:8000/contact  را باز کنید باید خروجی های مورد نظر را مشاهده کنید.

نکته : یادتان باشد برای اجرای برنامه لاراول به صورت بالا و با پورت 8000 باید دستور php artisan serve رو در ترمینال اجرا کنید.

خب تا اینجای کار توانستیم route های برنامه رو بنویسیم. در قسمت بعدی با view ها و موتور قالب Blade آشنا می شویم و این بار صفحات وبسایت را در قالب کدهای HTML و با استفاده از مفهومی به نام master page تولید خواهیم کرد.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
#5
کار با view ها و Blade
view ها یکی از عناصر سه گانه الگوی طراحی MVC هستند در لاراول در مسیر resources/views قرار دارند. با استفاده از تابع کمکی view می توانیم یک فایل ویو را render کنیم و نمایش دهیم. به مثال زیر  توجه کنید:
Route::get('/', function ()    {
   return view('greeting', ['name' => 'James']);
});
همانطور که مشاهده می کنید تابع view به عنوان پارامتر اول نام فایل view را بدون پسوند دریافت میکند و در صورتی که داده ای را هم قصد ارسال به ویو مورد نظر داریم به صورت یک ارایه انجمنی به عنوان پارامتر دوم به آن می دهیم که در فایل ویو به صورت یک متغیر قابل دریافت است.
در صورتی که فایل ویو داخل یک دایرکتوری دیگری باشد برای جدا کردن مسیر می توانید از نقطه استفاده کنید یا از همان / استفاده کنید.

لاراول از یک template engine  قوی به نام Blade استفاده می کند که خیلی هم آسان برای یادگیری هست و فایل های آن با پسوند blade.php ساخته می شود.
برای چاپ متغیرها یا هر دستور PHP که دارای یک خروجی می باشد از {{ }} استفاده میکنیم که این عبارت خروجی را escape می کند و مناسب برای زمانی است که ورودی را از کاربر دریافت میکنیم و در صورتی که یک تگ html را بخواهیم چاپ کنیم باید از {!! !!} استفاده کنیم.
همچنین برای استفاده از ساختارهای کنترلی و حلقه ها  ابتدا با استفاده از علامت @ آنها را می نویسیم مثلا ساختار if  را در مثال زیر مشاهده می کنید :
@if (count($records) === 1)
   I have one record!
@elseif (count($records) > 1)
   I have multiple records!
@else
   I don't have any records!
@endif
برای دیدن توضیحات و مثال های بیشتر می توانید به مستندات لاراول مراجعه کنید.

اگر به اکثر وبسایت ها مراجعه کنید می بینید که بخش هایی از صفحه در تمام صفحات مشترک است که برای این کار ما قبلا در PHP خام دو تا فایل header و footer را ضمیمه تمام صفحات خود میکردیم. در Blade شما می توانید یک قالب اصلی ایجاد کنید و آن را در تمام فایل های ویو که قصد استفاده از آن را دارید به ارث ببرید. افرادی که با ASP.NET کار کرده باشند با master page آشنایی دارند که این هم همان مفهوم را دارد.

برای تولید master page یک پوشه در پوشه resources/views به نام layouts ایجاد میکنم و سپس یک فایل به نام master.blade.php را داخل آن ایجاد کرده و کدهای زیر را داخل آن می نویسم :
<!doctype html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Blog - @yield('title')</title>
   <link rel="stylesheet" href="{{ asset('css/app.css') }}" type="text/css">
   @yield('css')
</head>
<body>
<div class="container">
   <div id="nav">
       <ul>
           <li><a href="{{ url('/') }}">صفحه اصلی</a></li>
           <li><a href="{{ url('about') }}">درباره ما</a></li>
           <li><a href="{{ url('contact') }}">تماس با ما</a></li>
       </ul>
   </div>
   <div id="content">
       @yield('content')
   </div>
</div>
@yield('js')
</body>
</html>

کلمه کلیدی yield که یک نام بهش می دهیم به ما میگه که این قسمت قرار است بعدا در فایل های ویو به ارث برده شده از این فایل master  پر شود. ما برای title و css و js و content هر صفحه یک yield تعریف کردیم که می توانیم در فایل view آنها را پرکنیم. فایل app.css که در مسیر public/css قرار دادم هم در تمام فایل های به ارث برده شده اعمال خواهد شد.
نکته : برای مسیردهی فایل های استاتیک مانند css ها و تصاویر و ... از تابع asset استفاده میکنیم و مسیر فایل را از پوشه public به عنوان ورودی به آن می دهیم و برای تعریف url به یک صفحه خاص مثلا برای لینک ها از تابع url استفاده میکنیم.
اکنون یک پوشه در مسیر resources/views به نام blog ایجاد می کنیم و فایل های index.blade.php و about.blade.php و contact.blade.php را در آن ایجاد میکنیم. کد های زیر را در هر صفحه قرار می دهیم:
index.blade.php :
@extends('layouts.master')

@section('title', 'Home')

@section('content')
   <h1>سلام به اولین برنامه من در لاراول خوش آمدید!</h1>
@endsection
about.blade.php :
@extends('layouts.master')

@section('title', 'About Me')

@section('content')
   <h1>این صفحه درباره ما می باشد</h1>
@endsection
contact.blade.php :
@extends('layouts.master')

@section('title', 'Contact Me')

@section('css')
   <style>
       h1 {
           color: #0000C2;
       }
   </style>    
@endsection

@section('content')
   <h1>این صفحه تماس با ما می باشد</h1>
@endsection

همانطور که مشاهده می کنید برای ارث بری فایل master  با استفاده از دستور extends که مسیر فایل master را به آن می دهیم آن را به صفحه اضافه میکنیم. همچنین yield هایی را که تعریف کردیم را با استفاده از دستور section که نام yield مورد نظر را به آن می دهیم و محتوای مورد نظر را می نویسیم و در انتها  دستور endsection را قرار می دهیم. بخش title چون محتوای خاصی ندارد و فقط می خواهیم یک رشته را به آن بدهیم به طور خلاصه تری نوشتم و رشته مورد نظر که همان عنوان ضفحه است را به عنوان پارامتر دوم به آن دادیم و نیاز به دستور endsection نمی باشد.
در فایل contact.blade.php هم از بخش css استفاده کردیم که فقط خاص همان صفحه خواهد بود و شما می توانید از فایل های جاوااسکریپت هم به همین صورت استفاده کنید.
کدهای فایل app.css هم فعلا به این صورت می باشد :
body {
   direction: rtl;
}

.container {
   margin: 0 auto;
   width: 960px;
   padding: 10px;
}

.error {
   color: #F40E0E;
}

اکنون باید فایل routes/web.php را به این صورت تغییر دهیم :
Route::get('/', function()
{
   return view('blog.index');
});

Route::get('/about', function()
{
   return view('blog.about');
});

Route::get('/contact', function()
{
   return view('blog.contact');
});


خب تو این قسمت توانستیم فایل های view برنامه را بسازیم و اگر دوباره url های موردنظر را باز کنید می بینید که این بار فایل های ویو رندر شده و متن با قالب html نمایش داده می شوند. شما می توانید با استفاده از css و فریمورک های سمت کلاینت مانند Twitter Bootstrap قالب های زیبایی رو طراحی و در برنامه تان استفاده کنید.

تو قسمت بعدی با کنترلرها آشنا خواهیم شد.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
#6
کار با کنترلرها
تو قسمت های قبلی ما درخواست هارو داخل همان فایل routes\web.php داخل یک تابع بی نام مدیریت می کردیم که این روش برای مواقعی که فقط می خواهیم یک صفحه استاتیک را رندر کنیم یا مواردی که نیاز به کدنویسی و پردازش خاصی نمی باشد مناسب است اما بهتر است از کنترلرها برای مدیریت درخواست ها استفاده کنیم.

کنترلرها در مسیر app/Http/Controllers قرار می گیرند و نام کنترلرها باید به صورت PascalCase نامگزاری شود و همچنین در انتهای ان کلمه Controller اضافه شود به طور مثال کنترلر UserController. در نامگزاری متدها هم بهتر است به صورت camelCase نامگزاری شوند.تمام کنترلرهایی که ایجاد میکنیم از کلاس Controller ارث برده می شوند.

کلاس های کنترلر دارای یک namespace به نام App\Http\Controllers می باشند که باید در ابتدای کلاس آن را ذکر کنیم در صورتی کلاس های شما داخل یک دایرکتوری دیگر داخل همان دایرکتوری Controllers باشند نام آن دایرکتوری به فضای نام باید اضافه شود.

هر کلاس دیگری که می خواهیم در کلاس کنترلر یا کلاس های دیگر استفاده کنیم باید به صورت کامل به همراه namespace آن بیاوریم و بهتر است آن را در ابتدای کلاس با استفاده از دستور use ایمپورت کنیم تا در هنگام استفاده در طول کلاس نیاز به نوشتن نام کلاس به همراه namespace آن نباشد.

ما یک کنترلر به نام BlogController را برای برنامه مان ایجاد می کنیم. یک روش به این صورت است که شما به صورت دستی فایل کنترلر را داخل پوشه Controllers ایجاد کنید اما روش بهتر که پیشنهاد میکنم استفاده کنید از روش Command Line است که با نوشتن دستور make:controller در ترمینال کلاس مورد نظر در پوشه Controllers ایجاد خواهد شد :
php artisan make:controller BlogController
اگر آپشن resource-- در انتهای دستور استفاده کنید در کنترلر چندتا اکشن با route های پیش فرض هم ساخته می شود که فعلا نیازی به آنها نداریم و در مبحث CRUD به آنها خواهیم پرداخت.

در کنترلر BlogController اکشن های زیر را اضافه کردم و سپس همان فایل های ویو را رندر کردم. برای نمونه یک داده هم به ویو index.blade.php به نام name ارسال کردم تا با نحوه دریافت و چاپ آن در ویو بیشتر آشنا شوید.

app/Http/Controllers/BlogController.php :
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class BlogController extends Controller
{
   public function index()
   {
       $name = "Hamo";
       return view('blog.index', ['name' => $name]);
   }

   public function about()
   {
       return view('blog.about');
   }

   public function contact()
   {
       return view('blog.contact');
   }
}


برای اینکه درخواست را به کنترلر ارسال کنیم باید در فایل routes/web.php به جای تعریف تابع بی نام یک رشته به آن بدهیم که ابتدا نام کنترلر و سپس علامت @ و بعد نام اکشن موردنظر را در آن بنویسیم.

routes/web.php :
//blog routs...
Route::get('/', 'BlogController@index');
Route::get('/about', 'BlogController@about');
Route::get('/contact', 'BlogController@contact');

اکنون فایل ویو index.blade.php رو هم به این صورت اصلاح میکنیم :
@extends('layouts.master')

@section('title', 'Home')

@section('content')
   <h1>سلام {{ $name }}, به اولین برنامه من در لاراول خوش آمدید!</h1>
@endsection

خب حالا می تونید دوباره آدرس های http://localhost:8000/ و http://localhost:8000/about و http://localhost:8000/contact رو اگر باز کنید می بینید که نتیجه به همان صورت قبل خواهد بود.

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

در قسمت بعدی با middleware ها آشنا خواهیم شد.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
#7
کار با Middleware ها
تمامی درخواست هایی که به برنامه وارد می شوند از طریق route ها یا کنترلرها قابل دریافت هستند و تو قسمت های قبلی مثال هایی از آن را انجام دادیم. با کلاس هایی به نام Middleware که در مسیر app/Http/Middleware قرار دارند می توانیم این درخواست ها را در صورت لزوم فیلتر کنیم به طور مثال می توانیم درخواست های ورودی به یک کنترلر خاص را فقط برای کاربرانی که احراز هویت شده اند قبول کنیم و در صورت عدم احرازهویت آنها را به صفحه login هدایت کند. در لاراول از طریق auth که یک Middleware از پیش تعریف شده است می توانیم این کار را انجام دهیم.
برای تعریف یک Middleware از دستور خط فرمان زیر استفاده میکنیم :
php artisan make:middleware OldMiddleware
در مثال بالا OldMiddleware نام Middleware است که در مسیر app/Http/Middleware قرار می گیرد.

اگر کلاس مورد نظر را باز کنید و در متد handle آن دستورات زیر را بنویسید:
<?php

namespace App\Http\Middleware;

use Closure;

class OldMiddleware
{
   /**
    * Run the request filter.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure  $next
    * @return mixed
    */
   public function handle($request, Closure $next)
   {
       if ($request->input('age') <= 200) {
           return redirect('home');
       }

       return $next($request);
   }

}

اگر مقدار ورودی age بزرگتر از 200 بود به درخواست اجازه عبور خواهد داد وگرنه آن را به صفحه خانگی home هدایت می کند. در واقع Middleware ها یک لایه هستند که درخواست را بازرسی کرده و اگر شرایط مورد نظر را نداشت به آن اجازه دسترسی نخواهند داد.

برای اینکه از این Middleware هایی که ایجاد میکنیم در برنامه استفاده کنیم ابتدا باید آن را در کلاس app/Http/Kernel.php ثبت کنیم. اگر می خواهیم Middleware مورد نظر هر درخواستی که وارد برنامه تان می شود را بررسی کند کلاس موردنظر را به پراپرتی middleware$ اضافه کنیم. همچنین می توانید middleware ها را داخل آرایه پراپرتی middlewareGroups$ در گروه middleware خاصی ثبت کنید به طور مثال گروه web که route های برنامه رو داخلش می نویسیم و در فایل routes/web.php قرار دارد اگر middleware را داخل آن ثبت کنیم فقط به route های گروه web اعمال خواهد شد.

اما اگر فقط می خواهید به یک route خاص اعمال گردد middleware مورد نظر را به پراپرتی routeMiddleware$ که یک آرایه انجمنی هست و کلید آرایه را یک نام مستعار برای آن در نظر میگیریم و در برنامه از این نام مستعار استفاده خواهیم کرد. به طور مثال کلاس OldMiddleware را به ان اضافه کردم و نام آن را old قرار دادم :
protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'old' => \App\Http\Middleware\OldMiddleware::class,
    ];

برای اعمال یک Middleware به یک route خاص به این صورت عمل میکنیم :
Route::get('admin/profile', ['middleware' => 'old', function () {
    //
}]);
طبق مثال بالا پارامتر دوم route را یک آرایه در نظر میگریم و برای تعریف middleware به آن از کلید middleware که مقدار آن نام خلاصه آن خواهد بود استفاده میکنیم و تمامی درخواست های ورودی به admin/profile که صفحه پروفایل ادمین است از فیلتر auth خواهند گذشت و اگر کاربر احرازهویت نشده بود به صفحه login ریدایرکت خواهد شد.

همچنین می توانیم متد middleware را هم به انتهای آن اضافه و نام Middleware را به آن بدهیم:
Route::get('admin/profile', function () {
    //
})->middleware('old');

اگر route به یک کنترلر است می توانیم در سازنده کلاس کنترلر هم آن را تعریف کنیم :
class UserController extends Controller
{
   /**
    * Instantiate a new UserController instance.
    *
    * @return void
    */
   public function __construct()
   {
       $this->middleware('auth');

       $this->middleware('log', ['only' => ['fooAction', 'barAction']]);

       $this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
   }
}

تو مثال بالا سه تا middleware را برای این کنترلر تعریف کردیم که log با استفاده از کلید only فقط به اکشن های fooAction و barAction اعمال خواهد شد و subscribed با استفاده از کلید except به همه اکشن های این کنترلر به جز fooAction و barAction اعمال خواهد شد.

خب حالا یک مثال با middleware ها انجام خواهیم داد تا کاربرد middleware ها رو بهتر درک کنید. یک Middlware به نام FunMiddleware طبق مراحل بالا ایجاد و آن را به نام fun در کلاس Kernel ثبت میکنیم.
در کلاس FunMiddleware داخل متد handle دستورات زیر را اضافه میکنیم و گفتیم که اگر ورودی به نام fun دارای مقدار true بود درخواست عبور کند وگرنه به صفحه اصلی برنامه ریدایرکت شود:
<?php

namespace App\Http\Middleware;

use Closure;

class FunMiddleware
{
   /**
    * Handle an incoming request.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure  $next
    * @return mixed
    */
   public function handle($request, Closure $next)
   {
       if ($request->input('fun') == false)
       {
           return redirect('/');
       }

       return $next($request);
   }
}

حالا یک route در فایل routes\web.php تعریف می کنیم و middleware را به این route می دهیم :
Route::post('/test', ['middleware' => 'fun', function () {
    return 'Your request is passed...';
}]);

داخل ویو about.blade.php هم که قبلا در مثال های قبلی ایجاد کرده بودیم فرم زیر را اضافه میکنیم :
@extends('layouts.master')

@section('title', 'About Me')

@section('content')
   <h1>این صفحه درباره ما می باشد</h1>

   <div style="border: 1px solid black;padding: 10px">
       <h3>مثالی از کاربرد Middleware :</h3>
       <form action="{{ url('test') }}" method="post">
           {{ csrf_field() }}
           <label for="fun">لطفا چک باکس زیر را تیک بزنید: </label>
           <input type="checkbox" name="fun" id="fun">
           <input type="submit" value="Fun">
       </form>
   </div>
@endsection

فرم بالا اکشن آن را به مسیر test قرار دادیم و حالا اگر چک باکس فرم را تیک بزنید و فرم را ارسال کنید چون مقدار ورودی fun برابر true خواهد بود رشته "Your request is passed..." برایتان نمایش داده خواهد شد اما اگر ان را تیک نزنید و ارسال کنید چون false است پس در FunMiddleware چون شرط ورودی fun برابر false است به آن اجازه عبور نمی دهد و آن را به صفحه اصلی برنامه ریدایرکت میکند.

در قسمت بعدی در مورد Request ها و Response ها در لاراول بیشتر آشنا خواهیم شد.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
تشکر شده توسط: meysam1366 , php , Renegad , ADMIN , fatima-php , captain , saman-arsenal , mohammadjavad , redhost
#8
Request و Response ها
همانطور که در PHP خام از طریق آرایه های عمومی GET , $_POST_$ به مقادیر درخواست های HTTP دسترسی داشته باشیم در لاراول هم از طریق کلاس Illuminate\Http\Request به این اطلاعات می توانیم دسترسی داشته باشیم. در کنترلرها می توانیم از طریق معماری dependency injection که در لاراول استفاده می شود از کلاس Request به روش type-hint در سازنده یا متد موردنظر کلاس کنترلر یک instance ایجاد کنیم.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * Store a new user.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->input('name');

        //
    }
}

همانطور که در مثال بالا مشاهده می کنید با صدازدن متد input از شی ای که از کلاس Request ایجاد کردیم توانستیم به مقدار ورودی به نام name دسترسی داشته باشیم.
برای دسترسی به تمام داده های ورودی از متد all استفاده می کنیم :
$input = $request->all();

این کلاس متدهای زیادی دارد که اطلاعات زیادی را به شما می دهد که می توانید با مراجعه به مستندات با آنها بیشتر آشنا شوید.

برای تولید پاسخ یا Response هم ساده ترین روش ایجاد یک پاسخ به صورت return یک رشته است که در مثال های قبلی بسیار با آن کار کردیم:
Route::get('/', function () {
    return 'Hello World';
});

روش بهتر این است که از کلاس Illuminate\Http\Response و تولید یک پاسخ با status مناسب و همچنین ست کردن header صفحه است. برای راحتی کار می توانیم از تابع response استفاده کنیم :
Route::get('home', function () {
    return response($content, $status)
                  ->header('Content-Type', $value);
});
در متغیر content$ محتوای پاسخ و در status$ وضعیت پاسخ که معمولا 200 در نظر می گیریم و در value$ نوع Content type پاسخ را قرار می دهیم به طور مثال اگر پاسخ به صورت html باشد از text/html استفاده می کنیم. این روش برای مواقعی که از ajax استفاده می کنیم مناسب است.

همچنین می توانیم پاسخ را به صورت یک json تولید کنیم :
return response()->json(['name' => 'Abigail', 'state' => 'CA']);
به متد json باید یک آرایه به عنوان ورودی بدهیم تا خروجی JSON آن را تولید کند.

البته ما بیشتر در برنامه پاسخ را در قالب یک فایل view تولید خواهیم کرد که در قسمت های قبلی با آن آشنا شدیم.

در مواقعی هم نیاز داریم پاسخ را به صورت یک ریدایرکت به صفحه دیگر تولید کنیم که در این صورت از تابع redirect استفاده میکنیم و url را به عنوان ورودی به آن می دهیم :
Route::get('dashboard', function () {
    return redirect('home/dashboard');
});

اگر بخواهیم ریدایرکت به صفحه ای که درخواست از آنجا آمده بکنیم از back استفاده می کنیم :
Route::post('user/profile', function () {
    // Validate the request...

    return back()->withInput();
});
متد withInput هم باعث می شود که داده های آن درخواست هم از بین نروند و بتوانیم به آنها دسترسی داشته باشیم که در فرم ها بسیار کاربردی هست.

با استفاده از with بعد از تابع redirect می توانیم یک پیغام را به صورت فلش به صفحه ای که ریدایرکت خواهیم شد هم ارسال کنیم که داده های فلش بعد از اولین درخواست از بین خواهند رفت که مناسب برای نمایش پیغام های خطا می باشد :
Route::post('user/profile', function () {
    // Update the user's profile...

    return redirect('dashboard')->with('status', 'Profile updated!');
});

برای چاپ آن هم در ویو از تابع session استفاده می کنیم :
@if (session('status'))
    <div class="alert alert-success">
        {{ session('status') }}
    </div>
@endif

تو این قسمت خواستیم با Request و Response ها آشنایی کافی داشته باشیم تا در قسمت های بعدی و در مثال های کاربردی که خواهیم زد از آنها استفاده کنیم.

در قسمت بعدی در مورد کار با دیتابیس بحث خواهیم کرد.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
تشکر شده توسط: ADMIN , fatima-php , mtcom , php , Renegad , captain , meysam1366 , mohammadjavad , Hamed , abdollah110110
#9
مقدمات کار با دیتابیس

قبل از اینکه بخواهیم با دیتابیس کار کنیم ابتدا در فایل env. تنظیمات مربوط به دیتابیس مانند DB_HOST و DB_DATABASE و DB_USERNAME و DB_PASSWORD را با مقادیر دیتابیس برنامه تان ست کنید به طور مثال من یک دیتابیس به نام laravel_blog در phpmyadmin ایجاد می کنم:
DB_HOST=127.0.0.1
DB_DATABASE=laravel_blog
DB_USERNAME=root
DB_PASSWORD=123456
دیتابیسی که در برنامه استفاده می کنم MySQL است اما در لاراول می توانید از PostgreSQL و SQLite و SQL Server هم استفاده کنید. در فایل پیکربندی config/database.php هم می توانید تنظیمات بیشتری را برای کار با دیتابیس اعمال کنید.

در لاراول به سه روش می توانیم با دیتابیس کار کنیم. روش اول به این صورت است که می توانیم با استفاده از facade کلاس DB و متدهای select, update, insert, delete و statement کوئری به دیتابیس بزنیم و از پارامتر binding هم به مانند PDO استفاده می کنیم که برای جلوگیری از حملات SQL Injection به کار می رود.
در مستندات لاراول مثال های زیادی وجود دارد که برای آشنایی بیشتر می توانید مطالعه کنید.

روش دوم کار با دیتابیس استفاده از Query Builder است. این روش نسبت به روش قبلی بهتر است و Syntax گویاتری دارد و برای آشنایی با آن مستندات لاراول را مطالعه کنید. مستندات لاراول خیلی واضح توضیح داده و مثال هم زده است و نیازی به توضیح دوباره و طولانی کردن مطالب نیست. فقط حتما با متدهای آن آشنا شوید چون در روش سوم که استفاده از Eloquent است و در برنامه از این روش استفاده خواهیم کرد از متدهای روش Query Builder زیاد استفاده خواهیم کرد.

در قسمت بعدی درباره کار با دیتابیس با Eloquent ORM آشنا خواهیم شد و مثالی کاربردی را انجام خواهیم داد.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
#10
 Eloquent ORM و بازیابی داده ها

روش سوم کار با دیتابیس استفادهاز  Eloquent ORM است. Eloquent یک پیاده سازی ActiveRecord است که به توسعه دهندگان برای کار با دیتابیس امکانات بهتری را می دهد و در این روش هر جدول در دیتابیس با یک کلاس Model در ارتباط است.

مدل ها در پوشه app فریمورک قرار خواهند گرفت که شما می توانید در هر زیر پوشه دیگری آنها را قرار دهید اما باید namespace انها را هم تغییر دهید به طور مثال اگر مدل ها را در پوشه ای به نام Models در پوشه app قرار دهیم namespace آن App\Models خواهد بود.

برای نامگزاری مدل هم آن را همانند نام کنترلرها به صورت PascalCase تعریف می کنیم یعنی حرف اول تمام کلمات باید بزرگ باشد. نام مدل را به صورت مفرد نام جدول نامگزاری می کنیم مثلا جدول users که جمع است مفرد آن user می باشد که نام مدل را User قرار می دهیم. اگر نخواهیم از این قانون پیروی کنیم و نام جدول و مدل را به هر نام دلخواه دیگری قرار دهیم کافی است در مدل مربوطه پراپرتی table$ را نام جدول موردنطرتان مقداردهی کنید.
protected $table = 'my_users';
همه مدل ها از کلاس eloquent مدل Illuminate\Database\Eloquent\Model به ارث برده می شوند.

برای تعریف مدل می توانید هم به صورت دستی فایل مدل را ایجاد کنید اما راه بهتر استفاده از دستور خط فرمان زیر می باشد :
php artisan make:model Post
اگر در انتهای دستور migration-- یا m-- را هم قرار دهیم برای مدل مربوطه یک فایل migration هم ایجاد می شود که می توانیم جدول موردنظر را در دیتابیس با migration ایجاد کنیم ولی چون در درس بعدی با migration آشنا خواهیم شد فعلا به صورت دستی در phpmyadmin و دیتابیس laravel_blog جدول posts را ایجاد می کنیم.

در جدول posts فعلا یک ستون کلید اصلی و AUTO_INCREMENT به نام id و یک ستون از نوع varchar به نام title و همچنین ستونی از نوع  text به نام body و یک ستون از نوع boolean به نام visible و پیش فرض ان را هم 0 قرار داده و ایجاد می کنیم.
لاراول به طور پیش فرض انتظار دارد که دوتا ستون به نام های created_at و updated_at هم در جدول وجود داشته باشد که تاریخ و زمان ایجاد و به روزرسانی رکورد در آن ثبت می شود که چون در مثال بالا آنها را قرار ندادیم در مدل موردنظر مقدار پراپرتی timestamps$ را برابر null  قرار می دهیم.
مدل Post به این صورت خواهد بود :
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{

   public $timestamps = null;
}
به جدول posts تعدادی رکورد اضافه کنید تا در ادامه با جدول موردنظر عملیات CRUD را انجام دهیم.

ایجاد کنترلر PostController
با استفاده از دستور خط فرمان زیر آن را ایجاد می کنیم :
php artisan make:controller PostController
اگر کنترلر موردنظر را بازکنید می بینید که تعدادی اکشن به طور پیش فرض در آن تعریف شده است که با استفاده از مسیردهی resource controller نیازی به تعریف route برای هر اکشن به صورت جداگانه نمی باشد و در این صورت کد کمتر و خلوت تری را در فایل routes\web.php خواهیم داشت.
در فایل routes\web.php مسیر زیر را به انتهای فایل اضافه کنید :
//post routes...
Route::resource('post', 'PostController');

حالا اگر دستور خط فرمان زیر را در ترمینال تایپ کنید :
php artisan route:list
لیستی از تمام route هایی که در برنامه تعریف کردید را مشاهده می کنید اطلاعاتی در مورد url و نام route و همچنین نوع Http Request و اکشن و کنترلری که آن را دریافت خواهد کرد و حتی middleware ای که برای آن تعریف کردیم را به ما می دهد که می توانید به این صورت route های ایجاد شده برای کنترلر PostController را مشاهده کنید. برای اطلاعات بیشتر به اینجا مراجعه کنید.

بازیابی داده ها
در متد index کنترلر PostController دستورات زیر را اضافه می کنیم :
public function index()
   {
       $posts = Post::all();
       return view('post.index', ['posts' => $posts]);
   }

همانطور که مشاهده کردید با استفاده از کلاس مدل Post و متد all تمامی رکوردهای جدول posts را بازیابی کرده و سپس  پوشهresources/views و پوشه  post  فایل index.blade.php را رندر کرده و داده ها را به آن ارسال می کنیم.

در ویو مورد نظر به این صورت آن را نمایش می دهیم :
@extends('layouts.master')

@section('title', 'posts')

@section('content')
   <h1>نمایش تمامی پست ها: </h1>
   @if ($posts->count() > 0)
       @foreach($posts as $post)
           <div>
               <h3><a href="{{ route('post.show', ['id' => $post->id]) }}">{{ $post->title }}</a></h3>
               <p>{{ $post->body }}</p>
           </div>
       @endforeach
   @else
       <p>هیچ مطلبی برای نمایش وجود ندارد.</p>
   @endif
@endsection


خروجی با eloquent به صورت collection هست که می توانید از متدهای کاربردی و مفید آن استفاده کنید که من در مثال بالا از count استفاده کردم.

در صورتی که بخواهیم از شرط برای بازیابی داده ها استفاده کنیم از متد where استفاده می کنیم و در پایان متد get را صدا می زنیم. متد where سه تا ورودی می گیرد که ورودی وسط operator شرط می باشد که برای مساوی = نیازی به نوشتن آن نداریم. (مانند مثال زیر)
public function index()
   {
       $posts = Post::where('visible', 1)->get();
       return view('post.index', ['posts' => $posts]);
   }

اگر به فایل ویو index.blade.php دقت کرده باشید من تمام عناوین پست ها را لینک کردم و از تابعی به نام route استفاده کردم که این تابع نام route را دریافت می کند که قبلا توضیح دادم چگونه نام route را متوجه شوید که به چه نامی می باشد. اگر route دارای پارامتر باشد هم پارامترها را به صورت یک آرایه به تابع route پاس می دهیم.
شما می توانید از تابع url هم استفاده کنید و نتیجه کار به همان صورت خواهد بود:
<h3><a href="{{ url('post/'.$post->id) }}">{{ $post->title }}</a></h3>

اکشن show در کنترلر PostController را هم به این صورت می نویسیم :
public function show($id)
   {
       $post = Post::find($id);
       return view('post.show', ['post' => $post]);
   }
با استفاده از متد find می توانیم با id پست موردنظر آن را واکشی کنیم. فایل ویو show.blade.php را هم ایجاد می کنیم :
@extends('layouts.master')

@section('title', 'show post')

@section('content')
   <div>
       <h3>{{ $post->id }} : {{ $post->title }}</h3>
       <p>{{ $post->body }}</p>
   </div>
   <a href="{{ route('post.index') }}">بازگشت</a>
@endsection

اگر کاربر به طور دستی یک id که در جدول posts موجود نیست را در url وارد کند یک exception ایجاد خواهد شد که برای مدیریت کردن این خطا می توانیم از متد findOrFail استفاده کنیم. ابتدا به کلاس کنترلر کلاس ModelNotFoundException را ایمپورت کنید :
use Illuminate\Database\Eloquent\ModelNotFoundException;

اکشن show را به این صورت تغییر دهید :
   public function show($id)
   {
       try {
           $post = Post::findOrFail($id);
           return view('post.show', ['post' => $post]);
       } catch (ModelNotFoundException $e) {
           return redirect()->route('post.index');
       }
   }

اکنون با رفتن به آدرس http://localhost:8000/post می توانیم نتیجه را در مرورگر ببینیم و اگر بر روی لینک کلیک کنیم هر پست را به طور جداگانه در صفحه دیگری مشاهده می کنیم و  اگر id که وجود ندارد را به آن بدهیم به صفحه http://localhost:8000/post ریدایرکت خواهیم شد.

امیدوارم که این جلسه برایتان مفید بوده باشد و به علت طولانی بودن مباحث دیتابیس ادامه مبحث و نحوه insert و update و delete کردن را در جلسه بعدی خواهیم آموخت.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
تشکر شده توسط: ADMIN , meysam1366 , Renegad , fatima-php , mtcom , mohammadjavad , captain
#11
Eloquent ORM و درج و به روزرسانی و حذف
در این قسمت می خواهیم ادامه مثال رو با درج رکورد و به روزرسانی و حذف آن ادامه بدهیم.
Insert
در کنترلر PostController در اکشن create فایل ویو create.blade.php را رندر می کنیم :
    public function create()
    {
        return view('post.create');
    }

در مسیر resources/views در پوشه post که قبلا ایجاد کردیم فایل create.blade.php را ایجاد و دستورات زیر را داخل آن قرار می دهیم :
@extends('layouts.master')

@section('title', 'Create New Post')

@section('content')
    <h3>ایجاد مطلب جدید</h3>
    <form action="{{ route('post.store') }}" method="post">
        {{ csrf_field() }}
        <div class="form-group">
            <label for="title" class="control-label">عنوان مطلب :</label>
            <div class="controls">
                <input type="text" name="title" id="title">
            </div>
        </div>
        <div class="form-group">
            <label for="body" class="control-label">متن مطلب:</label>
            <div class="controls">
                <textarea name="body" id="body" cols="30" rows="10"> </textarea>
            </div>
        </div>
        <div class="form-group">
            <div class="controls">
                <input type="submit" value="ایجاد مطلب جدید" class="btn btn-primary">
            </div>
        </div>
    </form>
@endsection

همانطور که می بینید یک فرم برای درج پست جدید ایجاد کردم. از کلاس های Twitter Bootstrap هم برای نمایش بهتر فرم استفاده کردم که شما هم می توانید بوت استرپ را به قالب master خود اضافه کنید. در ضمن در فرم ها حتما فیلد csrf_field را ایجاد کنید چون برای جلوگیری از حملات csrf توسط لاراول داشتن این فیلد ضروری است.
اطلاعات فرم به اکشن store ارسال خواهد شد بنابراین دستورات زیر را داخل اکشن store اضافه می کنیم :
    public function store(Request $request)
    {
        $post = new Post();
        $post->title = $request->input('title');
        $post->body = $request->input('body');
        $post->save();
        return redirect()->route('post.index');
    }
همانطور که مشاهده می کنید برای درج یک رکورد ابتدا باید از مدل مورد نظر یک شی ایجاد کنیم و سپس به طور مجزا attribute های مدل که همنام با ستونهای جدول موردنظر در دیتابیس هستند را با مقداری که از فرم آمده ست کنیم و در پایان برای درج رکورد متد save را صدا می زنیم.

روش بهتر و خلاصه تری به نام Mass Assignment هم هست که با استفاده از متد create و پاس دادن آرایه از داده های ارسالی از فرم می توانیم عمل درج را با یک خط کد انجام دهیم.
برای استفاده از این روش ابتدا باید یک پراپرتی به نام fillable$ به مدل اضافه کرده که این پراپرتی ستون هایی که به آن اجازه می دهیم از بیرون و توسط کاربر پر شوند را در آن به صورت یک ارایه مشخص می کنیم که در اصل یک لیست سفید ایجاد می کنیم.
در مدل Post آن را به این صورت اضافه می کنیم :
protected $fillable = ['title' , 'body', 'visible'];
یک پراپرتی به نام guarded$ متناظر با fillable وجود دارد که دقیقا نقطه مقابل آن هست و در آن لیست ستون هایی که اجازه ست شدن توسط کاربر را ندارند را مشخص می کنیم که در اصل یک لیست سیاه ایجاد خواهد کرد.
از هرکدوم از این پراپرتی ها استفاده کنید فرقی ندارد اما در کل هرکدام تعداد آیتم های کمتری داشتند استفاده از آن منطقی تر به نظر می رسد.

بعد از ایجاد پراپرتی fillable اکشن store را به این صورت تغییر دهید :
    public function store(Request $request)
    {
        Post::create($request->all());
        return redirect()->route('post.index');
    }

Update
برای به روزرسانی یک مطلب ابتدا یک دکمه ویرایش کنار هر مطلب در فایل index.blade.php قرار می دهیم :
        @foreach($posts as $post)
            <div>
                {{--<h3><a href="{{ route('post.show', ['id' => $post->id]) }}">{{ $post->title }}</a></h3>--}}
                <h3><a href="{{ url('post/'.$post->id) }}">{{ $post->title }}</a></h3>
                <p>{{ $post->body }}</p>
                <a href="{{ route('post.edit', ['id'=>$post->id]) }}" class="btn btn-warning">ویرایش</a>
            </div>
        @endforeach
توسط لینک بالا که route آن به اکشن edit خواهد بود id مطلب را هم ارسال کردیم و در متد edit ابتدا مطلب مورد نظر را از دیتابیس بازیابی می کنیم و سپس فایل ویو edit.blade.php را رندر کرده و آن را به صورت زیر می نویسیم :
    public function edit($id)
    {
        $post = Post::find($id);
        return view('post.edit', ['post' => $post]);
    }

حالا فایل ویو edit.blade.php را به صورت زیر می نویسیم :
@extends('layouts.master')

@section('title', 'Edit Post')

@section('content')
    <h3>ویرایش مطلب</h3>
    <form action="{{ route('post.update', ['id' => $post->id]) }}" method="post">
        {{ csrf_field() }}
        <input type="hidden" name="_method" value="PUT">
        <div class="form-group">
            <label for="title" class="control-label">عنوان مطلب :</label>
            <div class="controls">
                <input type="text" name="title" id="title" value="{{ $post->title }}">
            </div>
        </div>
        <div class="form-group">
            <label for="body" class="control-label">متن مطلب:</label>
            <div class="controls">
                <textarea name="body" id="body" cols="30" rows="10">{{ $post->body }}</textarea>
            </div>
        </div>
        <div class="form-group">
            <div class="controls">
                <input type="submit" value="ویرایش مطلب" class="btn btn-primary">
            </div>
        </div>
    </form>
@endsection

route فرم به اکشن update خواهد بود که id مطلب را هم به آن پاس می دهیم. برای آپدیت کردن و استفاده از اکشن update باید متد فرم را PUT یا PATCH قرار دهیم که چون HTML این متد را ساپورت نمیکند اینپوتی به نام method_ و با مقدار PUT و نوع hidden ایجاد کردیم.

حالا کافی است در متد update داده های ارسالی از فرم را دریافت و به روزرسانی را انجام دهیم :
    public function update(Request $request, $id)
    {
        $post = Post::find($id);
        $post->title = $request->input('title');
        $post->body = $request->input('body');
        $post->save();
        return redirect()->route('post.index');
    }
برای به روزرسانی ابتدا رکورد مورد نظر را بازیابی کردیم و سپس دوباره atrribute های آن را ست کردیم و در پایان متد save را صدا زدیم.

Delete
برای حذف رکورد هم یک دکمه حذف در فایل ویو index.blade.php اضافه می کنیم :
        @foreach($posts as $post)
            <div>
                {{--<h3><a href="{{ route('post.show', ['id' => $post->id]) }}">{{ $post->title }}</a></h3>--}}
                <h3><a href="{{ url('post/'.$post->id) }}">{{ $post->title }}</a></h3>
                <p>{{ $post->body }}</p>
                <a href="{{ route('post.edit', ['id'=>$post->id]) }}" class="btn btn-warning">ویرایش</a>

                <form action="{{ route('post.destroy', ['id'=>$post->id]) }}" method="post">
                    {{ csrf_field() }}
                    <input type="hidden" name="_method" value="DELETE">
                    <input type="submit" class="btn btn-danger" value="حذف">
                </form>
            </div>
        @endforeach
برای حذف رکورد باید آن را به اکشن destroy بفرستیم و چون این متد فقط HTTP Request های DELETE رو قبول میکند بنابراین دکمه را در قالب فرم و متد DELETE همانند حالت بروزرسانی عمل کردیم.
در متد destroy هم با استفاده از id مطلب می توانیم آن را بازیابی و سپس با متد delete حذف کنیم :
    public function destroy($id)
    {
        $post = Post::find($id);
        $post->delete();
        return redirect()->route('post.index');
    }

همچنین با استفاده از متد destroy هم می توانید رکورد را حذف کنید که می توانید id را هم به صورت پارامتر به آن بدهیم. با استفاده از این متد می توانیم چندین رکورد را به صورت همزمان حذف کنیم که id آنها را به صورت یک آرایه و یا پارامترهایی که با ویرگول از هم جدا شده اند به آن بدهیم.
در جلسات بعدی در مورد اعتبارسنجی یا validation هم مطالبی خواهیم داشت و سپس روی همین فرم های درج و آپدیت از اعتبارسنجی استفاده خواهیم کرد.

خب مبحث CRUD به پایان رسید و توانستیم به راحتی آن را انجام بدهیم. در جلسه بعدی migration را خواهیم آموخت و با استفاده از آن جداول دیتابیس خود را ایجاد می کنیم.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
تشکر شده توسط: meysam1366 , ADMIN , Renegad , fatima-php , captain , mtcom , mohammadjavad , Hamed
#12
Migration
Migration ابزاری هست به شما اجازه می دهد دیتابیس خود را مدیریت کنید و جداول خود را با آن ایجاد و یا دستکاری کنید. برای کار تیمی بسیار مناسب است و سایر اعضای تیم هم می توانند با تغییرات بوجود آمده دیتابیس آگاه شوند و در Migration دیگر وابسته به دیتابیس خاصی نیستید چون هیچ کد SQL ای نخواهید نوشت و دستوراتی که با Schema Builder خواهید نوشت با توجه توع دیتابیس برنامه تان که لاراول انها را پشتیبانی می کند اعمال خواهد شد.
ابتدا جدول posts که در بخش های قبلی در دیتابیس برنامه تان ایجاد کردید را حذف کنید تا در ادامه آن را migration ایجاد کنیم.

برای ایجاد یک migration در محیط خط فرمان دستور زیر را می نویسیم :
php artisan make:migration create_posts_table --create=posts
بعد از دستور make:migration نام فایل را به ان می دهیم که بهتره کاری که می خواهیم انجام دهیم را نام فایل قرار دهیم.اگر می خواهید جدولی را ایجاد کنید از آپشن create در انتهای دستور استفاده کنید و نام جدول را جلوی آن بنویسید.
در صورتی که در migration قصد دستکاری جدولی که قبلا ایجاد کرده ایم را داریم به طور مثال ستونی را به آن اضافه کنیم آپشن table را به انتهای دستور اضافه و نام جدول را به آن می دهیم:
php artisan make:migration add_votes_to_users_table --table=users

فایل migartion در پوشه database/migrations قرار می گیرد. migation ای که در بالا ایجاد کردیم (create_posts_table) را باز می کنیم در متد up ان با استفاده از Schema Builder ستون های جدول posts را تعریف می کنیم :
 
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->boolean('visible')->default(0);
            $table->timestamps();
        });
    }

همانطور که مشاهده می کنید داخل متد up ستون id که با increments تعریف می شود یعنی از نوع کلید اصلی و Auto-Increment می باشد و همچنین timestamps که ستون های created_at و updated_at را در جدول ایجاد خواهد کرد. یک ستون هم از نوع string به نام title و ستون دیگری به نام body از نوع text هم ایجاد کردیم. همچنین یک ستون از نوع boolean به نام visible و با مقدار پیش فرض 0 هم تعریف کردیم.
برای اینکه با این متدها که نوع ستون را مشخص می کنند آشنا شوید لطفا به مستندات لاراول مراجعه کنید و در آنجا در بخش Available Column Types با آنها بیشتر آشنا شوید.

در متد down باید عمل متناظر یا مخالف با کاری که در متد up انجام دادیم را بنویسیم که چون در مثال بالا قصد ایجاد جدول posts را داشتیم عمل drop کردن جدول posts در متد down قرار می گیرد.
    public function down()
    {
        Schema::drop('posts');
    }

اکنون دستور زیر را در محیط خط فرمان اجرا کنید :
php artisan migrate
دستور بالا تمام migartion هایی که در لاراول ایجاد کرده ایم و هنوز اجرا نشده اند را اجرا می کند. چون در لاراول به ظور پیش فرض دوتا migration دیگر هم وجود دارد که جداول users و password_resets را در دیتابیس برنامه تان ایجاد خواهد کرد.
در صورتی که اشتباهی در تعریف ستون ها داشتید یا اینکه قصد ویرایش آن را دارید می توانید با استفاده از rollback یکبار به عقب برگشته و migration اعمال شده را خنثی کرد و دوباره migrate را اجرا کنید:
php artisan migrate:rollback

در پایان اگر به دیتابیس برنامه تان در phpmyadmin مراجعه کنید مشاهده می کنید که جداول موردنظر ایجاد شده اند.
اکنون می خواهیم بین جدول users و posts یک رابطه ایجاد کنیم. هر پست توسط یک کاربر ایجاد شده است و هر کاربر هم ممکن است چندین پست ایجاد کرده باشد بنابراین رابطه یک به چند خواهد بود و کلید خارجی user_id را به جدول posts اضافه کنیم و سپس relation را ایجاد کنیم. بنابراین migration زیر را ایجاد می کنیم :
php artisan make:migration add_forien_key_user_id_to_posts_table --table=posts

سپس در فایل ایجاد شده در متد up آن دستورات زیر را می نویسیم :
    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->integer('user_id')->unsigned()->after('id');
            $table->foreign('user_id')->references('id')->on('users');
        });
    }


ابتدا ستونی از نوع integer و unsigned به نام user_id ایجاد کردیم و با استفاده از after آن را بعد از ستون id در جدول posts قرار دادیم. اگر after استفاده نکنید ستون بعد از آخرین ستون ایجاد خواهد شد.

نکته: برای نامگزاری ستون کلید خارجی بهتر است ابتدا نام مدلی که با مدل موردنظرمان ارتباط دارد و سپس پیشوند id_ را در انتهای آن قرار دهیم. در مثال بالا ما برای جدول posts یک مدل به نام Post و برای جدول users مدلی به نام User داریم بنابراین کلید خارجی آن user_id خواهد بود و اگر اینگونه نامگزاری نکینم بعدا در تعریف رابطه در مدل ها در Eloquent باید به طور دستی آن را ست کنیم.

همچنین ستون user_id را از نوع کلید خارجی تعریف کردیم و گفتیم که با ستون id در جدول users ارتباط دارد.

در متد down هم عمل متناظر را تعریف می کنیم:
    public function down()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->dropForeign('posts_user_id_foreign');
            $table->dropColumn('user_id');
        });
    }

ابتدا با استفاده از dropForeign کلید خارجی را حذف می کنیم. constraint کلید خارجی را به آن می دهیم که نامگزاری آن به این صورت است که ابتدا نام جدولی که کلید خارجی در ان تعریف شده سپس نام کلید خارجی و در پایان foreign را قرار داده و هرکدام را با علامت under_score (ـ) جدا می کنیم.
سپس در خط بعدی با استفاده از dropColumn ستون user_id را حذف می کنیم.

اگر دستور php artisan migrate را اجرا کنید ستون کلید خارجی و رابطه بین دو جدول users و posts ایجاد خواهد شد.

حتما مستندات لاراول و بخش migrations را مطالعه بفرمایید تا با مثال های بیشتری آشنا شوید. در قسمت بعدی تعریف یک رابطه در مدل ها با Eloquent را با یک مثال کاربردی خواهیم آموخت.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
تشکر شده توسط: Renegad , php , ADMIN , meysam1366 , fatima-php , mtcom , captain , mohammadjavad , Hamed
#13
Relationships در Eloquent
در دیتابیس تقریبا تمام جداول با یکدیگر ارتباط دارند که ارتباطات می توانند به صورت One-To-One و One-To-Many و یا Many-To-Many باشند که در قسمت قبلی توسط Schema Builder و Migration توانستیم نحوه تعریف کلید خارجی و ایجاد ارتباط بین دو جدول در دیتابیس برنامه را بیاموزیم.
برای اینکه بتوانیم از ارتباطات جداول در برنامه استفاده کنیم بایستی در مدل ها هم این ارتباطات را تعریف کنیم. طبق مثال قبلی ارتباط را بین دو جدول posts و users ایجاد می کنیم و فرض می کنیم هر مطلب توسط یک کاربر نوشته می شود و یک کاربر هم می تواند به چندین مطلب تغلق داشته باشد پس ارتباط بین آنها یک به چند است. در مدل User که سمت یک این ارتباط است یک تابع به نام posts را ایجاد می کنیم و به متد hasMany نام مدل Post را می دهیم:
    public function posts()
    {
        return $this->hasMany('App\Post');
    }
نکته: برای نامگزاری این تابع بهتر است آن را همنام مدلی که ارتباط با آن دارد و همچنین اگر ارتباط آن به صورت چندی است به صورت جمع وگرنه به صورت مفرد نامگزاری شود. در مثال بالا چون با مدل Post ارتباط چندی دارد آن را posts نامگزاری کردیم.

همچنین باید یک تابع هم در مدل Post ایجاد کنیم که تابع user را به صورت زیر تعریف می کنیم و به متد belongsTo هم نام مدل User را می دهیم :
    public function user()
    {
        return $this->belongsTo('App\User');
    }

اکنون اگر بخواهیم به تمام پست های ایجاد شده توسط یک کاربر خاص دسترسی داشته باشیم به این صورت عمل می کنیم :
$posts= User::find($id)->posts;
همچنین می توانیم از شرط هم به این صورت استفاده کنیم :
$posts= User::find(1)->posts()->where('title', 'like', '%itl%')->get();

اکنون می خواهیم تمام پست های بلاگ را در صفحه اصلی نمایش دهیم بنابراین در اکشن index کنترلر BlogController دستورات زیر را اضافه می کنیم :
    public function index()
    {
        $posts = Post::all();
        return view('blog.index', compact('posts'));
    }

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

اکنون در ویو blog/index.blade.php می توانید پست ها را نمایش دهید:
@extends('layouts.master')

@section('title', 'Home')

@section('content')
    <h2>به وبسایت آموزشی لاراول خوش آمدید!</h2>
    <div>
        <h3>آخرین مطالب :</h3>
        @if ($posts)
            <table class="table table-responsive">
                @foreach($posts as $post)
                    <tr>
                        <td><h3>{{ $post->title }}</h3></td>
                        <td>{{ $post->user->name }}</td>
                    </tr>
                    <tr>
                        <td colspan="2">
                            <p class="lead">{{ $post->body }}</p>
                        </td>
                    </tr>
                @endforeach
            </table>
        @endif
    </div>
@endsection

همانطور که می بینید برای دسترسی به نام کاربر ایجاد کننده پست به صورت post->user->name$ استفاده کردیم. که برای هر ستونی از جدول کاربر کافی است به جای name نام ستون مورد نظر را بنویسیم.

روشی که پست ها را واکشی کردیم (Post::all)باعث ایجاد مشکل N+1 خواهد یعنی به ازای هر user_id که از رکوردهای جدول posts پیدا خواهد کرد یک کوئری به جدول users خواهد زد که اگر 1000 تا رکورد داشته باشیم با کوئری که به جدول posts زده خواهد شد 1001 کوئری به دیتابیس خواهد زد که این اصلا خوب نیست. برای حل این مشکل باید از Eager Loading استفاده کنیم که با استفاده از with به صورت زیر متد index را ویرایش کنید:
    public function index()
    {
        $posts = Post::with('user')->get();
        return view('blog.index', compact('posts'));
    }
به متد with باید نام تابعی که برای تعریف ارتباط در مدل ایجاد کردیم را بدهیم. در روش بالا هر تعداد رکورد داشته باشیم فقط دوتا کوئری به دیتابیس زده می شود.

حالا اگر صفحه اصلی برنامه http://localhost:8000/ را مشاهده کنید نتیجه کار را مشاهده خواهید کرد.

در صورتی که بخواهیم یک پست جدید ایجاد کنیم و چون باید id کاربر در ستون user_id در جدول posts درج شود به صورت زیر می توانیم این کار را انجام دهیم:
        $user = User::find(1);
        $post = $user->posts()->create([
            'title' => 'A new Title',
            'body'  => 'A new Body...',
        ]);
ابتدا کاربر مورد نظر را با استفاده از id آن بازیابی کردیم و سپس با استفاده از create یک پست را ایجاد کردیم و به طور خودکار ستون user_id با id کاربر موردنظر پر خواهد شد. فقط در این روش که Mass Assignment می باشد حتما باید پراپرتی fillable$ یا guarded$ را در مدل Post تعریف کنیم.

خب در این قسمت تونستیم با ارتباطات و یک مثال کاربردی از آن آشنا شویم و در مباحث آتی در مورد ارتباط چند به چند هم مثالی خواهیم داشت. برای آشنایی بیشتر به مستندات لاراول و بخش relationships مراجعه کنید.
در قسمت بعدی با اعتبارسنجی و کلاس Request آشنا خواهیم شد.
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
تشکر شده توسط: ADMIN , php , captain , Renegad , mohammadjavad , tux-world , Hamed
#14
اعتبارسنجی داده ها
شما وقتی یک داده ای را از کاربر می گیرید و می خواهید در دیتابیس ذخیره کنید باید اطمینان حاصل کنید که داده وارد شده همان چیزی است که شما انتظار دارید و در غیر اینصورت باید پیغام خطای مناسب را برای کاربر نمایش دهیم. برای اینکار از اعتبارسنجی یا validation استفاده می کنیم.
در لاراول ما می تونیم به چندین صورت اعتبارسنجی را انجام دهیم. روش اول اعتبارسنجی به صورت دستی است که در ابتدا از این روش استفاده خواهیم کرد. ما در برنامه قبلا یک کنترلر به نام PostController داشتیم که در اکشن store آن مطلب جدید را در دیتابیس ذخیره می کردیم اکنون دوباره ان را ویرایش می کنیم:
    public function store(Request $request)
    {
        $validation = Validator::make($request->all(), [
            'title' => 'required|max:255',
            'body'  => 'required',
        ]);
        if ($validation->fails()) {
            return redirect()->back()->withInput()->withErrors($validation);
        }
        Post::create($request->all());
        return redirect()->route('post.index');
    }
همانطور که مشاهده می کنید کلاس Validator و متد make را فراخوانی کردیم که این متد دوتا پارامتر می گیرد اولین پارامتر آن آرایه ای از داده ها که از طرف کاربر و فرم ارسال شده است و پارامتر دوم هم آرایه ای از rule های اعتبارسنجی را قرار دهید. rule هایی که استفاده کردم required یعنی این ستون الزامی است و همچنین max که حداکثر طول وارد شده توسط کاربر برای فیلد title تا ۲۵۵ کاراکتر قرار دادم. برای آشنایی با تمام rule ها می تونید به اینجا مراجعه کنید.

اگر اعتبارسنجی fails باشد به صفحه قبل ریدایرکت می کنیم و با استفاده از withErrors پیغام های خطا را نیز به صفحه ویو ارسال می کنیم و همچنین با withInput نیز داده هایی که کاربر وارد کرده را هم نگه می داریم و از بین نمی رود و در ویو با استفاده از تابع old قابل دستیابی است.
صفحه ویو در پوشه resources/views/post/create.blade.php رت به این صورت تغییر می دهیم:
@extends('layouts.master')

@section('title', 'Create New Post')

@section('content')
    <h3>ایجاد مطلب جدید</h3>
    <form action="{{ route('post.store') }}" method="post">
        {{ csrf_field() }}
        <div class="form-group">
            <label for="title" class="control-label">عنوان مطلب :</label>
            <div class="controls">
                <input type="text" name="title" id="title" value="{{ old('title') }}">
                @if($errors->has('title'))
                    {!! $errors->first('title', '<span class="error">:message</span>') !!}
                @endif
            </div>
        </div>
        <div class="form-group">
            <label for="body" class="control-label">متن مطلب:</label>
            <div class="controls">
                <textarea name="body" id="body" cols="30" rows="10">{{ old('body') }}</textarea>
                @if($errors->has('body'))
                    {!! $errors->first('body', '<span class="error">:message</span>') !!}
                @endif
            </div>
        </div>
        <div class="form-group">
            <div class="controls">
                <input type="submit" value="ایجاد مطلب جدید" class="btn btn-primary">
            </div>
        </div>
    </form>
@endsection
اکنون اگر فرم را خالی ارسال کنید پیغام خطا را مشاهده می کنید. متغیر errors$ رو با متد has بررسی کردیم که آیا وجود دارد و در این صورت اولین خطای هر فیلد را با متد first چاپ کردیم. متد first یک پارامتر دومی هم می تونیم بهش بدیم که پیغام را داخل یک تگ html برامون چاپ کنه و طبق الگویی که نوشتم یعنی باید حتما از یک placeholder مثلا به نام message: استفاده کنید.

فارسی کردن پیغام های خطا
فقط مشکلی که اینجا هست پیغام های خطا انگلیسی هستند شما برای ست کردن پیغام های خطا هم می تونید به چند روش عمل کنید به طور مثال پیغام های خطا راهم به صورت یک آرایه تعریف کنید و به عنوان پارامتر سوم به متد make بدهید اما روش بهتر این است که در پوشه resources/lang یک پوشه جدید به نام fa ایجاد کنیم و سپس تمام محتویات داخل پوشه en را داخل ان هم کپی کنیم. سپس در فایل validation.php می توانید تمام پیغام های خطای rule های مورد نظرتون رو ترجمه کنید مثلا :
'required'             => 'پرکردن فیلد  :attribute الزامی است.',
همچنین در انتهای فایل validation.php در آرایه attributes باید برای attribute لیبل فارسی آن را هم بنویسیم :
    'attributes' => [
        'title' => 'عنوان',
        'body'  => 'متن',
    ],

در پایان هم باید در پوشه Config و فایل app.php مقدار locale را به fa تغییر دهیم. اکنون اگر دوباره فرم را خالی ارسال کنید پیغام های خطای فارسی را مشاهده خواهید کرد.

روش دوم کار با اعتبار سنجی استفاده از متد داخلی validate در کنترها هست :
    public function store(Request $request)
    {
        $this->validate($request, [
            'title' => 'required|max:255',
            'body'  => 'required',
        ]);
        Post::create($request->all());
        return redirect()->route('post.index');
    
این روش خلاصه تر هم هست و اگر اعتبارسنجی دارای خطایی باشد خودش به طور اتوماتیک به صفحه قبلی ریدایرکت و پیغام های خطا را هم ست می کند.

استفاده از کلاس Form Request
روش سوم استفاده از کلاس های Form Request است که بازهم کد خلاصه تری به شما می دهد و هنگامی که در یک کنترلر چند اکشن از یک اعتبارسنجی مشابه استفاده می کنند خیلی مناسب است.
برای ایجاد این کلاس از دستور زیر در خط فرمان استفاده می کنیم:
php artisan make:request StoreBlogPostRequest
کلاس StoreBlogPostRequest در پوشه app/Http/Request قرار می گیرد که در آن ابتدا در متد rules قوانین اعتبارسنجی موردنظرمان را مشخص می کنیم:
    public function rules()
    {
        return [
            'title' => 'required|unique:posts|max:255',
            'body'  => 'required',
        ];
    }
خروجی متد authorize را هم فعلا true قرار می دهیم اما در کل در این متد چک می کنیم که آیا کاربری که مثلا قصد update کردن یک پست را دارد آیا مجوز این کار را دارد و نویسنده این پست هست یا خیر.

حالا در متد store به جای استفاده از کلاس Request از StoreBlogPostRequest استفاده می کنیم:
    public function store(StoreBlogPostRequest $request)
    {
        Post::create($request->all());
        return redirect()->route('post.index');
    }
هر درخواستی که به این اکشن ارسال کنید ابتدا در کلاس StoreBlogPostRequest اعتبارسنجی می شود و اگر دارای خطا باشد به صفحه قبل ریدایرکت و خطاها در در متغیر errors$ قابل دستیابی هستند.
فقط یادتان باشد برای استفاده از هر کلاس در کلاس دیگر در لاراول باید آن را به همراه namespace آن کامل بنویسید یا آن را ابتدای فایل ایمپورت کنید:
use App\Http\Requests\StoreBlogPostRequest;

اگر دوباره فرم را خالی ارسال کنید نتیجه کار مثل دو روش قبلی خواهد بود. برای آشنایی تکمیلی حتما بخش validation مستندات لاراول رو مطالعه کنید.

در قسمت بعدی با کلاس های Html و Form و نحوه اضافه شدن آنها به لاراول نسخه 5 و کار با آنها آشنا خواهیم شد .
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
تشکر شده توسط: mohammadjavad , ADMIN , Renegad , captain , Hamed , abdollah110110
#15
تا اینجای کار هم فایل های پروژه را در اختیار شما قرار می دهم. بعد اینکه پوشه blog را داخل پوشه root نرم افزار شبیه ساز سرورتان extract کردین (مثلا در مسیر c:\xampp\htdocs) با دستور php artisan migrate تمام جداول برنامه رو ایجاد کنید. سپس داخل جداول میتونید چند تا رکورد هم درج کنید.همچنین در فایل env. می توانید تنظیمات مربوط به دیتابیس برنامه را با توجه به سیستم خودتان تغییر دهید.

لینک دانلود پروژه
موفقیت، نتیجه تشخیص درست است؛ تشخیص درست، نتیجه تجربه است؛ تجربه نیز اغلب نتیجه تشخیص نادرست است.



پاسخ
تشکر شده توسط: mohammadjavad , ADMIN , Renegad




کاربران در حال بازدید این موضوع: 1 مهمان