توسعه Eloquent Collection
درک صحیح از اجزا مختلف ORM امکان توسعه و افزودن امکانات و ابزار های جدید به این بخش ها را می دهید . مثلا زمانی که با Eloquent ORM کار میکنید با دانستن نوع خروجی آن (نتیجه یک رکورد و نمونه ایجاد شده از مدل باشد و یا اینکه نتیجه حاصل از چند رکورد Multi-Recordset و آرایه ای از مدل ها باشد ) میتوان امکانات خوبی در زمانی که خروجی از نوع آرایه مدل ها است اضافه کرد.
نکته : زمانی که با ORM ازنوع Active Record Design کار میکنید این مفهوم را در ذهنتان داشته باشید ” یک مدل یعنی نتیجه حاصل از واکشی یک رکورد از بانک اطلاعاتی با خواص شی گرایی به همراه تمامی ارتباطی بین جداولی خود ” و سعی کنید این مفهوم را تا آنجا که میتوانید در دنیای شی گرایی بسط دهید …
نحوه ایجاد یک eloquent collection
در لاراول تمامی نتایج که توسط Eloquent استخراج می شوند در صورتی که بیش از یک رکورد multi-recordset باشد ، بصورت یک نمونه کلاس collection که آرایه رکورد ها را در خود دارد استخراج می شود. این شیء از یک interface با نام IteratorAggregate پیاده سازی شده است که به موجب آن میتوانید به صورت رکورد به رکورد وبا استفاده از دستوراتی مانند foreach آنها را پیمایش کنید .
همچنین این شیء توابع و helper های گوناگونی درخود دارد که میتوانید از آنها استفاده کنید. برای مثال چک کنید آیا collection شما رکوردی بامقدار PrimaryKey عدد ۵۵ در خود دارد یا خیر؟
1 2 3 4 5 |
$users = User::all(); if ($users->contains(55)) { // رکورد مورد نظر موجود می باشد } |
همچنین میتوانید به شکل زیر عمل کنید :
1 2 3 |
User::all()->each(function($user){ echo $user->username; }); |
در این آموزش قصد داریم متد هایی از این قبل را در پروژه پیاده سازی کنیم که در مواقع لزوم از آنها استفاده کنیم . خب ، کلاس پایه ای collection در فضای نام \Illuminate\Support\Collection قرار دارد که این کلاس مجموعه ای از توابع کاربردی که برروی کالکشن ما قابل اجرا می باشد درخود دارد . و کلاسی که eloquent برای ایجاد کالکشن از آن استفاده میکند در فضای نام Illuminate\Database\Eloquent\Collection قرار دارد که از کلاس پایه ای collection مشتق شده است .
به جرات میتوان گفت لاراول یک فریموورک بسیار قدرتمند و انعطاف پذیر میباشد که به روش های بسیاری میتوان هسته آن و قابلیت های آن را توسعه داد. که در این مورد میتوانیم یک کلاس دیگر ایجاد کنیم که از کلاس Illuminate\Database\Eloquent\Collection مشتق شود و تمامی متد ها جدید مورد نیاز را در آن قرار میدهم سپس در مدل مان یک تابع newCollection ایجاد میکنیم (این کلاس در کلااس پایه Eloquent Model وجود دارد که در اینجا آن را override میکنیم )
1 2 3 4 5 6 7 8 9 10 11 |
ابتدا یک کلاس با نام CustomCollection ایجاد میکنیم که باید از Illuminate\Database\Eloquent\Collection مشتق شود . <?php namespace Extensions; class CustomCollection extends \Illuminate\Database\Eloquent\Collection { // یک متدبه عنوان تست در آن ایجاد میکنیم public function foo() { // ... } } |
سپس متد زیررا به یکی از مدل های خود اضافه میکنیم .
1 2 3 4 5 6 7 |
class Order extends Eloquent { // Override the parent method public function newCollection(array $models = Array()) { return new Extensions\CustomCollection($models); } } |
حال با فراخوانی دستور زیر
1 |
Order::all()->foo() |
متد foo از کلاس CustomCollection فراخوانی خواهد شد که با این روش میتوانید متد های جدید و یا انواع مختلفی از Collection ها را برای مدل های خود ایجاد کنید .
برای مثال ما میخواهیم یک متد داشته باشیم که نتیجه حاصل از کوئری مان را به صورت یک bootstrapTable تبدیل کند. در قسمت زیر مراحل انجام آن را برای شما شرح خواهیم داد .
ابتدا یک متد با نام toTable و به صورت زیر در کلاس CustomCollection ایجاد میکنیم :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
// app/extensions/customCollection.php <?php namespace Extensions; class CustomCollection extends \Illuminate\Database\Eloquent\Collection { public function toTable($options = null) { $header = $atts = ''; $items = $this->toArray(); $header_keys = array_keys($items[0]); if(!is_null($options)) { if(array_key_exists('only', $options)) { $header_keys = $options['only']; } if(array_key_exists('attributes', $options)) { $attr = $options['attributes']; } } // Thead if(is_null($options) || (!isset($options['header']) || isset($options['header']) && $options['header'] != false)) { $header = "<thead><tr>"; foreach ($header_keys as $value) { $header .= "<th>" . ucwords(str_replace('_', ' ', $value)) . "</th>"; } $header .= "</tr></thead>"; } // Tbody $tbody = "<tbody>"; foreach ($items as $values) { $tbody .= "<tr>"; foreach($header_keys as $key){ $tbody .= "<td>" . $values[$key] . "</td>"; } $tbody .= "</tr>"; } $tbody .= "</tbody>"; // Build attributes (id, class, style etc) if(isset($attr)) { foreach ($attr as $key => $value) { $atts .= " " . $key . "='" . $value . "'"; } } // Return only Tbody (if table == false) if(!is_null($options) && isset($options['table']) && $options['table'] == false) return $tbody; // Return table with attributes (class, id, style etc) else return "<table $atts>" . $header . $tbody . "</table>"; } } |
برای اینکه این متد را در تمامی مدل ها بتوانیم استفاده کنیم ، یک کلاس با نام BaseModel ایجاد میکنیم که بعدا مدل هایمان را به این کلاس extends میکنیم .
1 2 3 4 5 6 7 8 9 |
<?php class BaseModel extends Eloquent { public function newCollection(array $models = Array()) { return new Extensions\CustomCollection($models); } } |
سپس جهت تست آن مدل User را به کلاس BaseModel اکستند میکنیم :
1 2 3 4 5 6 7 8 |
<?php use Illuminate\Auth\UserInterface; use Illuminate\Auth\Reminders\RemindableInterface; class User extends BaseModel implements UserInterface, RemindableInterface { // code here } |
و در پایان لذت استفاده از آن را تجربه کنید 🙂
۱ – در کنترلر کد زیر را قرار دهید :
1 2 3 4 5 6 7 8 |
$users = User::all(); $options = array( 'only' => array('id', 'first_name', 'last_name', 'username', 'email', 'bio'), 'attributes' => array( 'class' => 'table', 'id' => 'tbl1' ) ); return View::make('user.index') ->with('users', $users) ->with('options', $options) |
۲ فایل view در مسیر user/index.blade.php ایجاد کیند و کد زیر را در آن قرار دهید :
1 2 3 4 |
@extends('layouts.master') @section('content') {{ $users->toTable($options) }} @stop |
خروجی حاصل از آن
به انتخاب خود میتوانید آن را به صورت زیر نیز استفاده نمایید :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// جدول را بدون هدر نمایش میدهد $options = array( 'only' => array('id', 'first_name', 'last_name', 'username', 'email', 'bio'), 'attributes' => array( 'class' => 'table table-striped', 'id' => 'tbl1' ), 'header' => false ); // فقط بلاک tbody را نمایش میدهد, // بدون تگ // header و Table $options = array( 'only' => array('id', 'first_name', 'last_name', 'username', 'email', 'bio'), 'attributes' => array( 'class' => 'table table-striped', 'id' => 'tbl1' ), 'table' => false ); // با تظیم // "table => false" // ویو را میتوانید سفارشی تر کنید برای مثال : @extends('layouts.master') @section('content') <table class="table table-striped"> <thead> <tr> <th>ID</th><th>Username</th><th>Email</th> </tr> </thead> {{ $users->toTable($options) }} </table> @stop |
در قسمت بعدی این آموزش متد های متنوع دیگری را شرح خواهیم داد .
موفق و پیروز باشید
درود برشما
از چه ide استفاده می کنید!؟
با سلام. از phpstorme
سلام ، خیلی عالی و کاربردی بود دستتون درد نکنه اگه توابع بیشتری رو معرفی کنید ممنون میشم و منتظر آموزش های مفید تون هستیم.