Validation Rules
وقتی بحث از ورود اطلاعات توسط کاربر پیش میاد بحث امنیت هم بعد از اون مطرح میشه. در لاراول روالی برای validate کردن اطلاعات کاربر داریم که با استفاده از اون هم میشه داده های مجاز رو تعیین کرد هم نکات امنیتی رعایت میشه.
نکته : در پایگاه داده لاراول از متد های PDO استفاده میشه که از SQL Injection جلوگیری می کنه.
لاراول برای پیاده سازی سیستم validation از شئ request استفاده میکنه ، که در اون قوانین (rules) تعریف می کنه که به ازای هر فیلد مقادیر مجاز و غیر مجاز تعیین میشه و در ازای مقدار مجاز کد اجرا میشه و در ازای مقدار غیر مجاز کد ادامه پیدا نمی کنه و شئ $errors
ایجاد میشه .
اعتبار سنجی از Route تا Controller
فرض کنید ما در Route دو endpoint تعریف کردیم که یکی فرم ثبت محصول را نمایش می دهد و دیگری با متد post اطلاعات کاربر را برای ذخیره به controller می فرستد :
Route::get('admin/new-product/','ProductController@create')->name('product.create'); Route::post('admin/','ProductController@store')->name('product.save');
ما در قسمت controller متدی با نام newProduct داریم که فرم ساخت محصول را به کاربر نمایش می دهد و متد دیگری با نام saveProduct داریم که با استفاده از اطلاعاتی که کاربر بوسیله فیلد های فرم ارسال کرده یک محصول می سازه.
namespace App\Http\Controllers; use Illuminate\Http\Request; use App\products; class ProductController extends Controller { public function create() { return view('product.create'); } public function store(Request $request) { $product = $request->all(); $validatedData = $request->validate([ 'name' => 'required|unique:products', 'price' => 'required|numeric', ]); $product = $request->except('_token'); $result = products::create($product); return redirect('/products'); } }
- متد store شئ request را فراخوانی کرده است که بوسیله آن بتواند از متد validate استفاده کرده و validation rule را تعریف کند.
- نوع شئ request هم مهم است که از چه کلاسی instanse شده باشد. شئ request که در مثال بالا استفاده شده از
Illuminate\Http\Request
می باشد . - ما به ازای هر فیلد می توانیم validation rule تعریف کنیم که قوانین آن را می توانید از اینجا مشاهده فرمایید. علاوه بر آن می توان از لیست ترجمه های فایل lang.validation (مثلا برای زبان انگلیسی در مسیر
laravel\resources\lang\en\validation.php
)قوانین اعتبار سنجی را ببینیم.
همچنین می توان از Custome Request استفاده کرد و در متد rule
آن validation rule را پیاده سازی کرد.
public function rules() { return [ 'name' => 'required|unique:products', 'price' => 'required|numeric', 'weight' => 'numeric|nullable' ]; }
فرم ساخت محصول به شکل زیر خواهد بود . در متد newProduct فایل new-product.blade.php فراخوانی شده است که حاوی اطلاعات زیر است :
@include('errors.crate') <form action="{{route('save.product')}}" method="POST"> {{ csrf_field() }} <div class="form-group"> <input type="text" class="form-control" id="product-name" name="name" value="{{old('name')}}" aria-describedby="productName" placeholder="product name"> <small id="nameHelp" class="form-text text-muted">{{__('general.name_tip')}}</small> </div> <div class="form-group"> <input type="text" class="form-control" id="product-price" name="price" value="{{old('price')}}" placeholder="price"> <small id="priceHelp" class="form-text text-muted">{{__('general.price_tip')}}</small> </div> <button type="submit" class="btn btn-primary">Submit</button> </form>
- همان طور که می دانید هر Route دارای یک نام است که Path آن با استفاده از تابع
route
قابل دسترسی است که ما در کد بالا مسیر مسیر route دوم را به عنوان action فرم تعیین کرده ایم همچنین متد post را برای آن انتخاب کرده ایم که هر دوی این موارد بر اساس route دوم است. - تابع کمکی
old
برای این است که کاربر اگر به هر دلیل (محتمل ترین دلیل عدم تایید از سوی validation rule های request است) محصولش ساخته نشد داده هایی که در فرم وارد کرده برایش باقی بماند. - در ابتدای کد قالب
errors.create
فراخوانی شده است که محتوای آن خطاهایی است که در صورت غیر مجاز شناخته شدن مقادیر فیلد های کاربر نمایش داده می شود. - تابع کمکی
csrf_field
برای جلوگیری csrf protection استفاده می شود و وجود آن اجباری است و در غیر اینصورت request نامعتبر و خطای 419 یعنی همان session expired هدایت می شوید.
نتیجه فرم ساخت محصول
نتیجه فرم ساخت محصول به همراه اعتبارسنجی آن دو حالت زیر است :
تایید مقادیر فیلد ها و ساخت محصول : در این صورت فیلد ها از فیلتر validation rules رد شده و معتبر شناخته شده و ادامه کد ها اجرا شده و محصول ساخته می شود.
عدم تایید مقادیر فیلد ها و خطا : فیلد ها توسط validation rules نامعتبر شناخته شده و ادامه کدها (ساخت محصول و بازگشت به داشبورد) اجرا نمی شود و صفحه جاری (new-product.blade.php) به همراه شئ $errors
دوباره درخواست داده می شود و ما با استفاده از متد all خطاهای بوجود آمده بر اساس validation rules را چاپ می کنیم.
نحوه چاپ خطاها که در فایل create.blade.php
با مسیر errors.create
فراخوانی شده بود به شکل زیر می باشد:
@if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif
CSRF Protection
ما Middleware مشترکی در route هامون داریم تحت عنوان web که در اون درخواستی معتبره که token مربوط به لاراول رو داشته باشه.
پس هر request معتبر در لاراول باید csrf token رو داشته باشه در غیر این صورت به صفحه 404 هدایت میشه. حال این که request ما از نوع post و از طریق فرم باشه که باید خودمون این فیلد رو بهش اضافه کنیم (بوسیله Helper Function) و یا از طریق route باشه که خود لاراول این کار رو برای ما می کنه.
ما در فرم ها با استفاده از تابع csrf_field می تونیم این فیلد رو به صورت hidden بسازیم و درخواستمون رو معتبر کنیم.
Creation Form Request
مثلا ما با استفاده از دستور زیر یک Request می سازیم.
php artisan make:request StoreBlogPost
در کلاس Request شخصی که توسط ما ساخته شده باشه متدی وجود داره که به وسیله اون میشه validation rule رو تعریف کرد و در نهایت در controller ما به وسیله شئ ساخته شده می تونیم validate رو انجام بدیم.
public function rules() { return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]; }
خوب متد بالا برای تعریف validation rule بود و در نهایت با استفاده از شئ ساخته شده از Custome Request می تونیم فیلتر رو انجام بدیم.
public function store(StoreBlogPost $request) { // The incoming request is valid... // Retrieve the validated input data... }
خوب همون طور که مشاهده می کنید ما از شئ $request
مورد نظر بر گرفته از کلاس StoreBlogPost استفاده می کنیم که خود validation رو انجام میده. پس ما دیگر نیازی به اجرای متد validate نداریم.
Validation Rules
در controller ما تعدادی قانون با استفاده از متد validate ایجاد کردیم . در این قسمت میخوایم در رابطه با نحوه ایجاد اون ها و لیست validation rule ها صحبت کنیم.
validation rule چه در Custom Request باشه (متد rule
ایجاد شده موجود در Request ایجاد شده) و چه با استفاده از متد validate
از شئ request موجود در Illuminate\Http\Request
آرایه ای خواهد بود که هر المنت آن متشکل از نام فیلد مورد نظر برای فیلتر گذاری . به شکلی که index هر المنت از آرایه نام فیلد و مقدار آن برابر validation rule هایی که با | از هم جدا شده اند.
برخی از rule های موجود در Laravel Validation Rules :
accepted : این rule به معنای این است که این فیلد حتما باید مقدار true و یا 1 بگیرد. این فیلد برای تعیین چک باکس قبول قوانین و مقررات مناسب است.
required : به معنای الزامی بودن فیلد است.
unique:table,column : به معنای یکتا بودن مقدار فیلد در پایگاه داده بر اساس column می باشد. در صورتی که column تعیین نشده باشد از نام فیلد به عنوان نام ستون استفاده می شود.
'name' => 'required|unique:products'
در مثال بالا نام باید در جدول products و در ستون name یکتا باشد. یعنی نام وارد شده در جدول از قبل وجود نداشته باشد. (this name is already taken).
numeric : فیلد فقط مقادیر عددی را می پذیرد.
Error Messages
متن خطاهای چاپ شده در صورت غیر مجاز بودن مقدار فیلد در صورتی که ما از شئ instanse شده از کلاس Illuminate\Http\Request
استفاده کنیم در فایل resourses/lang/en/validation.php
موجود است. حال این که در config/app.php شما مقدار locale را برابر چه مقداری قرار داده باشید زبان مورد نظر لود می شود.
ساختار های زیر قابل ترجمه هستند:
:attribute
نمایش داده می شوند.'attributes' => [ 'name' => 'نام' ],
:attribute
که به معنی field name است. در مثال زیر :attribute نام فیلد می باشد.'accepted' => ' فیلد :attribute باید پذیرفته شود'
'custom' => [ 'attribute-name' => [ 'rule-name' => 'custom-message', ], ],
'custom' => [ 'weight' => [ 'numeric' => 'لطفا در وارد کردن متن دقت فرمایید', ], ]
Custom Request Error Messages
اگر ما برای validation یک Request ایجاد کرده باشیم می توانیم متون خطا را در متد messages
با همان فرمتی که در بالا توضیحاتش رو دادیم به ازای Custom Validation Attributes و Validation Language Lines و Custom Validation Language Lines وارد کنیم.
<?php /** * Get custom messages for validator errors. * * @return array */ public function messages() { return [ 'name.required' => 'please fill name field', 'name.unique' => 'product name must be unique, :attribute is already taken', 'price.required' => 'please fill price field', 'price.numeric' => 'price field must be numeric', 'weight.numeric' => 'weight field must be numeric' ]; }
نکته : در صورتی که مقادیر را در این متد set نکنیم از مسیر پیش فرض فایل های ترجمه قسمت validation میخواند. مثلا در مسیر resourses/lang /en/validation.php
به ازای زبان انگلیسی در تنظیمات config.
دیدگاهتان را بنویسید