php artisan make:model Flight
دستور بالا یک Model بهنام Flight در همان پوشهی پیشفرض، یعنی app ایجاد میکند.
اگر میخواهید همزمان با ساخت Model، یک Migration به Database آن ایجاد کنید، به جای دستور بالا از یکی از دستورات زیر استفاده کنید.
php artisan make:model Flight --migration
php artisan make:model Flight -m
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
//
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'My_Fflights';
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'flight_id';
}
همچنین بهصورت پیش فرض نوع Primary Key یک Integer با روند صعودی در نظر گرفته میشود. اگر بخواهید که نوع آن Integer نباشد، میتوانید از دستور زیر استفاده کنید و به طور مثال نوع آن را به String تغییر دهید.
<?php
class Flight extends Model
{
/**
* The "type" of the auto-incrementing ID.
*
* @var string
*/
protected $keyType = 'string';
}
اگر بخواهید که Primary Key روند صعودی نداشته باشد، کافی است incrementing$ را به صورت زیر false کنید.
<?php
class Flight extends Model
{
/**
* Indicates if the IDs are auto-incrementing.
*
* @var bool
*/
public $incrementing = false;
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;
}
اگر میخواهید که این ستونها، مقدار زمانی را با Format دلخواه شما ذخیره کنند، میتوانید از دستور زیر استفاده کنید.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The storage format of the model's date columns.
*
* @var string
*/
protected $dateFormat = 'U';
}
همچنین اگر بخواهید نام این ستونها را تغییر دهید، باید از دستور زیر استفاده کنید.
<?php
class Flight extends Model
{
const CREATED_AT = 'creation_date';
const UPDATED_AT = 'last_update';
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The connection name for the model.
*
* @var string
*/
protected $connection = 'connection-name';
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The model's default values for attributes.
*
* @var array
*/
protected $attributes = [
'delayed' => false,
];
}
در دستور بالا میتوانیم مقدار پیشفرض هر تعداد دیگر Attribute را در آرایه attributes$ وارد کنیم.
<?php
$flights = App\Flight::all();
foreach ($flights as $flight) {
echo $flight->name;
}
در این دستور ابتدا از مدل Fight تمام دادهها را گرفتیم. سپس توسط حلقه foreach، اسم تمام آنها را echo کردیم.
همانطور که در بالا دیدید، اگر از ()all استفاده کنیم، تمام دادهها در اختیار ما قرار میگیرند. اما اگر تمام آنها را نخواهیم و تنها به تعدادی از آنها با یک شرط خاص نیاز داشته باشیم، میتوانیم از where استفاده کنیم.
$flights = App\Flight::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();
$flight = App\Flight::where('number', 'FR 900')->first();
$freshFlight = $flight->fresh();
همچنین همانطور که در دستور زیر آمده است، پس از تغییر یک داده Database میتوانیم مانند همان دستور بالا، از دستور ()refresh نیز استفاده کنیم.
$flight = App\Flight::where('number', 'FR 900')->first();
$flight->number = 'FR 456';
$flight->refresh();
$flight->number; // "FR 900"
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});
اگر دادههای ما ۱۰۰۰ تا باشد، آن دادهها بهصورت دقيق در ۵ دسته یا Index قرار میگیرند. حال اگر مانند مثال بالا ۱۱۵۰ داده داشته باشیم، ۵ Index که هر کدام ۲۰۰ مقدار یا Value دارند و ۱ Index که ۱۵۰ مقدار دارد، دریافت میشود.
در دستور بالا ما دادهها را در بخشهای ۲۰۰ تایی دریافت میکنیم و بر روی هر کدام از آنها توسط حلقه foreach میتوانیم یک عمل انجام دهیم.
use App\Destination;
use App\Flight;
return Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
])->get();
return Destination::orderByDesc(
Flight::select('arrived_at')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->limit(1)
)->get();
// Retrieve a model by its primary key...
$flight = App\Flight::find(1);
دستور بالا دادهای را برمیگرداند که id یا Primary Key آن برابر با 1 است.
$flights = App\Flight::find([1, 2, 3]);
این دستور همانند دستور اول است با این تفاوت که علاوه بر دریافت دادهای که id یا Primary Key آن برابر با 1 است، دادههایی که Primary Key آنها برابر با 2 و 3 هست را نیز برمیگرداند.
// Retrieve the first model matching the query constraints...
$flight = App\Flight::where('active', 1)->first();
دستور بالا تمام دادههایی که ستون active آن برابر با 1 باشد را دریافت میکند و توسط ()first اولین داده را نشان میدهد.
// Shorthand for retrieving the first model matching the query constraints...
$flight = App\Flight::firstWhere('active', 1);
این دستور، کوتاه شدهی دستور سوم یعنی استفاده از ()first است.
حال امکان دارد دادهای با مشخصاتی که وارد کردیم وجود نداشته باشد. در این صورت اگر بخواهیم هنگامی که این اتفاق افتاد، یک دادهی دیگر، یک متن یا هر چیز دیگری نمایش داده شود، میتوانیم از firstOr استفاده کنیم.
$model = App\Flight::where('legs', '>', 100)->firstOr(function () {
// ...
});
درون تابعی که در firstOr قرار دارد، میتوانیم هر Query قرار دهیم تا در صورتی که در جدول Flights هیچ دادهای با legs بزرگتر از ۱۰۰ وجود نداشت، آن Query اجرا شود.
همچنین firstOr میتواند یک آرایه دریافت کند تا بر روی تمام Indexهای آن آرایه، یک Query اجرا کند.
$model = App\Flight::where('legs', '>', 100)
->firstOr(['id', 'legs'], function () {
// ...
});
$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();
اگر در دستورات بالا Model پیدا نشود، برای کاربر یک Error 404 نمایش داده میشود.
$count = App\Flight::where('active', 1)->count();
$max = App\Flight::where('active', 1)->max('price');
از count برای دریافت تعداد دادهها، max برای دریافت بزرگترین داده و sum برای دریافت جمع دادهها استفاده میکنیم.
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Flight;
use Illuminate\Http\Request;
class FlightController extends Controller
{
/**
* Create a new flight instance.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Validate the request...
$flight = new Flight;
$flight->name = $request->name;
$flight->save();
}
}
در دستور بالا ابتدا یک متغیر به نام flight ایجاد میکنیم. سپس name را از طریق Http Request کاربر دریافت میکنیم و آن را برابر با نام متغیر flight قرار میدهیم. حال توسط ()save این درخواست به Database ارسال شده و در ستون name پایگاه داده (Database) ذخیره میشود.
در صورتی که timestamps$ را false نکرده باشیم، پس از ()save یک داده در Database، بهطور خودکار ستونهای created_at و updated_at آن، مقداری برابر با زمان Server میگیرد.همچنین برای ایجاد یک داده میتوانیم از create که همانند save عمل میکند نیز استفاده کنیم.
$flight = App\Flight::create(['name' => 'Flight 10']);
$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();
در صورتی که timestamps$ را false نکرده باشیم، پس از ()save یک دادهای که از قبل در Database وجود داشته است، بهطور خودکار ستون updated_at آن، مقداری برابر با زمان Server میگیرد.
همچنین برای بروزرسانی چند داده با مشخصاتی خاص، میتوانیم آنها را با یک Query که تنها دادههایی که آن مشخصات خاص را دارند برمیگرداند، دریافت کنیم و پس از آن از update استفاده کنیم.
App\Flight::where('active', 1)
->where('destination', 'San Diego')
->update(['delayed' => 1]);
در دستور بالا، تمام پروازهایی که مقدار active آن برابر با 1 و مقدار destination یا مقصد آن برابر با San Diego است شناسایی شده و توسط update، مقدار delayed آنها برابر با 1 میشود.
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->isDirty(); // true
$user->isDirty('title'); // true
$user->isDirty('first_name'); // false
$user->isClean(); // false
$user->isClean('title'); // false
$user->isClean('first_name'); // true
$user->save();
$user->isDirty(); // false
$user->isClean(); // true
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->save();
$user->wasChanged(); // true
$user->wasChanged('title'); // true
$user->wasChanged('first_name'); // false
$user = User::find(1);
$user->name; // John
$user->email; // john@example.com
$user->name = "Jack";
$user->name; // Jack
$user->getOriginal('name'); // John
$user->getOriginal(); // Array of original attributes...
هنگامی که یک Attribute را در fillable وارد کنیم، بهطور خودکار تمام Attributeهای دیگر guarded میشوند. همچنین اگر یک Attribute را در guarded وارد کنیم، بهطور خودکار تمام Attributeهای دیگر fillable میشوند.در مثال بالا که تنها میخواهیم ۲ Attribute غیرقابل پر کردن باشند، بهتر است بهجای وارد کردن Attribute هایی که قابل پر کردن میباشند در fillable، آن Attribute هایی که غیرقابل پر کردن هستند را در guarded وارد کنیم.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name'];
}
در دستور بالا Attribute که میتواند مقدار بگیرد را در fillable وارد کردیم، پس تمام Attributesها به جز name که fillable است، guarded میباشند.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = ['price'];
}
در دستور بالا Attribute که نمیتواند مقدار بگیرد را در guarded وارد کردیم، پس تمام Attributesها به جز price که guarded است، fillable میباشند.
// Retrieve flight by name, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
// Retrieve flight by name, or create it with the name, delayed, and arrival_time attributes...
$flight = App\Flight::firstOrCreate(
['name' => 'Flight 10'],
['delayed' => 1, 'arrival_time' => '11:30']
);
// Retrieve by name, or instantiate...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
// Retrieve by name, or instantiate with the name, delayed, and arrival_time attributes...
$flight = App\Flight::firstOrNew(
['name' => 'Flight 10'],
['delayed' => 1, 'arrival_time' => '11:30']
);
// If there's a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99, 'discounted' => 1]
);
$flight = App\Flight::find(1);
$flight->delete();
App\Flight::destroy(1);
App\Flight::destroy(1, 2, 3);
App\Flight::destroy([1, 2, 3]);
App\Flight::destroy(collect([1, 2, 3]));
$deletedRows = App\Flight::where('active', 0)->delete();
در دستور بالا، تمام پروازهایی که غیرفعال هستند را از Database حذف میکنیم.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Flight extends Model
{
use SoftDeletes;
}
پس از use کردن SoftDeletes باید ستون deleted_at را به جدول Database اضافه کنیم. این ستون به صورت پیشفرض از نوع DateTime و با پشتیبانی از Carbon است.
Schema::table('flights', function (Blueprint $table) {
$table->softDeletes();
});
حال وقتی از delete برای حذف داده استفاده کنیم، به صورت خودکار ستون deleted_add مقداری برابر با زمان Soft Delete کردن داده را میگیرد و پس از آن وقتی یک Query بر روی آن Model بزنیم، میبینیم که آن Model مانند حذف کردنهای معمولی، دیگر وجود ندارد با این تفاوت که با استفاده از trashed میتوانیم همان Model که Soft Delete شده بود را بررسی کنیم.
if ($flight->trashed()) {
//
}
$flights = App\Flight::withTrashed()
->where('account_id', 1)
->get();
همچنین از withTrashed میتوانیم در Queryهای ارتباطی یا relationship Queryها نیز استفاده کنیم.
$flight->history()->withTrashed()->get();
$flight->restore();
همچنین برای restore کردن چند دادهی خاص از Model، میتوانیم به شکل زیر عمل کنیم.
App\Flight::withTrashed()
->where('airline_id', 1)
->restore();
// Force deleting a single model instance...
$flight->forceDelete();
// Force deleting all related models...
$flight->history()->forceDelete();
$shipping = App\Address::create([
'type' => 'shipping',
'line_1' => '123 Example Street',
'city' => 'Victorville',
'state' => 'CA',
'postcode' => '90001',
]);
$billing = $shipping->replicate()->fill([
'type' => 'billing'
]);
$billing->save();
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AgeScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('age', '>', 200);
}
}
<?php
namespace App;
use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope(new AgeScope);
}
}
در این صورت به طور مثال، درخواست دریافت تمام کاربران یک سایت یا همان ()User::all برابر با کد SQL زیر میشود.
select * from `users` where `age` > 200
<?php
namespace App;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope('age', function (Builder $builder) {
$builder->where('age', '>', 200);
});
}
}
User::withoutGlobalScope(AgeScope::class)->get();
اگر Global Scope را توسط Closure ایجاد کردید، برای حذف آن باید به شکل زیر عمل کنید.
User::withoutGlobalScope('age')->get();
همچنین اگر میخواهید به جای حذف تنها یک Global Scope، همه یا چند تا از آنها را حذف کنید، میتوانید از دستورات زیر استفاده کنید.
// Remove all of the global scopes...
User::withoutGlobalScopes()->get();
// Remove some of the global scopes...
User::withoutGlobalScopes([
FirstScope::class, SecondScope::class
])->get();
Scopeها همیشه باید یک instance از query builder را return کنند.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Scope a query to only include popular users.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
/**
* Scope a query to only include active users.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeActive($query)
{
return $query->where('active', 1);
}
}
$users = App\User::popular()->active()->orderBy('created_at')->get();
همچنین برای ترکیب چند Local Scope از or به شکل زیر در ابتدای Query استفاده میکنیم.
$users = App\User::popular()->orWhere(function (Builder $query) {
$query->active();
})->get();
با این حال، از آن جا که این روش میتواند کمی دشوار باشد، لاراول یک روش بهتر یعنی orWhere را ارائه میدهد که از طریق این Method بدون استفاده از Closure ها، میتوانید این Scopeها را مانند زنجیر به هم متصل کنید.
$users = App\User::popular()->orWhere->active()->get();
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Scope a query to only include users of a given type.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param mixed $type
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeOfType($query, $type)
{
return $query->where('type', $type);
}
}
حال میتوانید هنگام فراخوانی Scope، به شکل زیر به آن یک پارامتر اختصاص دهید.
$users = App\User::ofType('admin')->get();
if ($post->is($anotherPost)) {
//
}
<?php
namespace App;
use App\Events\UserDeleted;
use App\Events\UserSaved;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The event map for the model.
*
* @var array
*/
protected $dispatchesEvents = [
'saved' => UserSaved::class,
'deleted' => UserDeleted::class,
];
}
حال مانند دستور بالا، Indexهای دلخواهی را در آرایه dispatchesEvents$ همراه با Value هایی برابر با Classهای نظیر آن تعریف میکنیم. پس از آن شما میتوانید از event listnereها برای مدیریت Eventهای خود استفاده کنید.
<?php
namespace App;
use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::created(function ($user) {
//
});
}
}
php artisan make:observer UserObserver --model=User
دستور بالا یک Observer جدید بهنام UserObserver در App/Observers ایجاد میکند. در صورتی که پوشهی Observers از قبل موجود نباشد، با اجرای دستور بالا این پوشه بهصورت خودکار ایجاد میشود.
Observerها در ابتدا به شکل زیر هستند:
<?php
namespace App\Observers;
use App\User;
class UserObserver
{
/**
* Handle the User "created" event.
*
* @param \App\User $user
* @return void
*/
public function created(User $user)
{
//
}
/**
* Handle the User "updated" event.
*
* @param \App\User $user
* @return void
*/
public function updated(User $user)
{
//
}
/**
* Handle the User "deleted" event.
*
* @param \App\User $user
* @return void
*/
public function deleted(User $user)
{
//
}
/**
* Handle the User "forceDeleted" event.
*
* @param \App\User $user
* @return void
*/
public function forceDeleted(User $user)
{
//
}
}
برای register کردن یک Observer، از متد observe در Model استفاده میکنیم. برای این کار باید به شکل زیر دستور observe را در متد boot یکی از Service Provider ها، بهطور مثال AppServiceProvider تعریف کنیم.
<?php
namespace App\Providers;
use App\Observers\UserObserver;
use App\User;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
User::observe(UserObserver::class);
}
}
جمعبندی
همیشه یکی از اصلیترین دغدغههای برنامه نویسانی که با زبان PHP کار میکردند، ایجاد ارتباط بین برنامه و Database، زدن Queryهای مختلف برای اضافه کردن، حذف کردن، بروزرسانی و اعمال تغییراتی هر چند کوچک بر روی دادههای Database و مشکلاتی از این دست بود. همانطور که در مقدمه این مقاله گفتیم، یکی از بزرگترین مزایای فریم ورک لاراول، استفاده از Eloquent ORM است که به تمام دغدغههایی که گفتیم پایان داده است. آشنا بودن هر چه بهتر با laravel eloquent ، سرعت کار ما را چندین برابر افزایش و کیفیت برنامههای ما را به مراتب بهتر میکند.
اگر به یادگیری بیشتر لاراول علاقه داری میتونی در دوره آموزش لاراول کاربردی (بسته پروژه محور) شرکت کنی، این دوره شامل ۱۲ پروژه کاربردی و پر استفاده در دنیای واقعی است، که تمامی پروژهها به صورت کامل برنامه نویسی خواهند شد، تا دانشجو بتواند با روند ایجاد و تکمیل پروژه به صورت کامل آشنا شود.
یه مقاله بسیار عالی و کاربردی بود. واقعا لذت بردم و خوشحالم که همچین مقاله کاملی به زبان فارسی در سونلرن منتشر شده.
ممنون بابت حسن نظرتون :)