Floquent: Mutators & Casting
معرفی
لوازم جانبی، جهشدهندهها و ریختهگری ویژگی به شما امکان میدهند تا مقادیر ویژگی Eloquent را هنگام بازیابی یا تنظیم آنها در نمونههای مدل تغییر دهید. به عنوان مثال، ممکن است بخواهید از رمزگذار لاراول برای رمزگذاری یک مقدار در زمانی که در پایگاه داده ذخیره می شود، استفاده کنید، و سپس زمانی که به آن در مدل Eloquent دسترسی پیدا می کنید، ویژگی را به طور خودکار رمزگشایی کنید. یا، ممکن است بخواهید یک رشته JSON را که در پایگاه داده شما ذخیره می شود، زمانی که از طریق مدل Eloquent شما قابل دسترسی است، به یک آرایه تبدیل کنید.
Accessors و Mutators
تعریف Accessor
هنگامی که یک Accessor به یک مقدار مشخصه Eloquent دسترسی پیدا می کند، تبدیل می کند. برای تعریف یک Accessor، یک متد محافظت شده در مدل خود ایجاد کنید تا ویژگی قابل دسترسی را نشان دهد. این نام روش باید مطابق با نمایش "camel case" از ویژگی اصلی مدل / ستون پایگاه داده در صورت لزوم باشد.
در این مثال، یک Accessor برای ویژگی تعریف می کنیم
first_name
. هنگام تلاش برای بازیابی مقدار مشخصه، Accessor به طور خودکار توسط Eloquent فراخوانی می شود
first_name
. همه متدهای Accessor/mutator ویژگی باید نوع بازگشتی را اعلام کنند
Illuminate\Database\Eloquent\Casts\Attribute
:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Casts\Attribute;use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * Get the user's first name. */ protected function firstName(): Attribute { return Attribute::make( get: fn (string $value) => ucfirst($value), ); }}
همه متدهای دسترسی
Attribute
نمونه ای را برمی گردانند که نحوه دسترسی به ویژگی و در صورت تمایل، جهش را مشخص می کند. در این مثال، ما فقط نحوه دسترسی به ویژگی را تعریف می کنیم. برای انجام این کار،
get
آرگومان را به
Attribute
سازنده کلاس ارائه می کنیم.
همانطور که می بینید، مقدار اصلی ستون به Accessor ارسال می شود و به شما امکان می دهد مقدار را دستکاری و برگردانید. برای دسترسی به مقدار Accessor، میتوانید به سادگی به
first_name
ویژگی در یک نمونه مدل دسترسی داشته باشید:
use App\Models\User; $user = User::find(1); $firstName = $user->first_name;
اگر می خواهید این مقادیر محاسبه شده به آرایه / نمایش JSON مدل شما اضافه شود، باید آنها را اضافه کنید .
ساخت اشیاء با ارزش از چندین ویژگی
گاهی اوقات دسترسی شما ممکن است نیاز داشته باشد که چندین ویژگی مدل را به یک "شیء ارزش" واحد تبدیل کند. برای انجام این کار،
get
بسته شدن شما ممکن است آرگومان دومی را بپذیرد
$attributes
که به طور خودکار به بسته شدن ارائه میشود و حاوی آرایهای از تمام ویژگیهای فعلی مدل است:
use App\Support\Address;use Illuminate\Database\Eloquent\Casts\Attribute; /** * Interact with the user's address. */protected function address(): Attribute{ return Attribute::make( get: fn (mixed $value, array $attributes) => new Address( $attributes['address_line_one'], $attributes['address_line_two'], ), );}
ذخیره ابزار دسترسی
هنگام برگرداندن اشیاء مقدار از دسترسیها، هر تغییری که در شیء مقدار ایجاد شده است، قبل از ذخیره مدل بهطور خودکار با مدل همگامسازی میشود. این امکان پذیر است زیرا Eloquent نمونه های بازگردانده شده توسط Accessor ها را حفظ می کند تا بتواند هر بار که Accessor فراخوانی می شود همان نمونه را برگرداند:
use App\Models\User; $user = User::find(1); $user->address->lineOne = 'Updated Address Line 1 Value';$user->address->lineTwo = 'Updated Address Line 2 Value'; $user->save();
با این حال، ممکن است گاهی اوقات بخواهید حافظه پنهان را برای مقادیر اولیه مانند رشته ها و بولی ها فعال کنید، به خصوص اگر از نظر محاسباتی فشرده باشند. برای انجام این کار، می توانید
shouldCache
در هنگام تعریف Accessor خود از روش استفاده کنید:
protected function hash(): Attribute{ return Attribute::make( get: fn (string $value) => bcrypt(gzuncompress($value)), )->shouldCache();}
اگر میخواهید رفتار کش کردن اشیاء ویژگیها را غیرفعال کنید، میتوانید
withoutObjectCaching
در هنگام تعریف ویژگی از متد استفاده کنید:
/** * Interact with the user's address. */protected function address(): Attribute{ return Attribute::make( get: fn (mixed $value, array $attributes) => new Address( $attributes['address_line_one'], $attributes['address_line_two'], ), )->withoutObjectCaching();}
تعریف جهش دهنده
یک جهشگر مقدار مشخصه Eloquent را هنگامی که تنظیم می شود تبدیل می کند. برای تعریف یک mutator، ممکن است
set
هنگام تعریف ویژگی خود، آرگومان را ارائه دهید. بیایید یک mutator برای
first_name
ویژگی تعریف کنیم. زمانی که بخواهیم مقدار
first_name
ویژگی را در مدل تنظیم کنیم، این جهشدهنده بهطور خودکار فراخوانی میشود:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Casts\Attribute;use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * Interact with the user's first name. */ protected function firstName(): Attribute { return Attribute::make( get: fn (string $value) => ucfirst($value), set: fn (string $value) => strtolower($value), ); }}
بسته شدن mutator مقداری را که روی ویژگی تنظیم شده است دریافت می کند و به شما امکان می دهد مقدار را دستکاری کنید و مقدار دستکاری شده را برگردانید. برای استفاده از mutator خود، فقط باید
first_name
ویژگی را روی یک مدل Eloquent تنظیم کنیم:
use App\Models\User; $user = User::find(1); $user->first_name = 'Sally';
در این مثال،
set
callback با مقدار
Sally
. سپس mutator
strtolower
تابع را به نام اعمال می کند و مقدار حاصل از آن را در آرایه داخلی مدل تنظیم می کند
$attributes
.
جهش چندین ویژگی
گاهی اوقات ممکن است جهشدهنده شما نیاز به تنظیم چندین ویژگی در مدل اصلی داشته باشد. برای انجام این کار، می توانید یک آرایه را از
set
بسته شدن برگردانید. هر کلید در آرایه باید با یک ویژگی زیرین / ستون پایگاه داده مرتبط با مدل مطابقت داشته باشد:
use App\Support\Address;use Illuminate\Database\Eloquent\Casts\Attribute; /** * Interact with the user's address. */protected function address(): Attribute{ return Attribute::make( get: fn (mixed $value, array $attributes) => new Address( $attributes['address_line_one'], $attributes['address_line_two'], ), set: fn (Address $value) => [ 'address_line_one' => $value->lineOne, 'address_line_two' => $value->lineTwo, ], );}
ریخته گری ویژگی
ریختهگری ویژگی عملکردی شبیه به اکسسوریها و جهشدهندهها را بدون نیاز به تعریف روشهای اضافی در مدل خود ارائه میکند. در عوض، روش مدل شما
casts
روشی مناسب برای تبدیل ویژگیها به انواع دادههای رایج ارائه میدهد.
متد
casts
باید آرایهای را برگرداند که در آن کلید، نام مشخصهای است که فرستاده میشود و مقدار، نوعی است که میخواهید ستون را به آن ارسال کنید. انواع بازیگران پشتیبانی شده عبارتند از:
-
array
-
AsStringable::class
-
boolean
-
collection
-
date
-
datetime
-
immutable_date
-
immutable_datetime
-
decimal:<precision>
-
double
-
encrypted
-
encrypted:array
-
encrypted:collection
-
encrypted:object
-
float
-
hashed
-
integer
-
object
-
real
-
string
-
timestamp
برای نشان دادن ریختن ویژگی، اجازه دهید
is_admin
ویژگی را که در پایگاه داده ما به عنوان یک عدد صحیح (
0
یا
1
) ذخیره میشود به یک مقدار بولی تبدیل کنیم:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * Get the attributes that should be cast. * * @return array<string, string> */ protected function casts(): array { return [ 'is_admin' => 'boolean', ]; }}
پس از تعریف cast،
is_admin
مشخصه همیشه هنگام دسترسی به آن به یک Boolean فرستاده می شود، حتی اگر مقدار اساسی در پایگاه داده به عنوان یک عدد صحیح ذخیره شود:
$user = App\Models\User::find(1); if ($user->is_admin) { // ...}
اگر نیاز به اضافه کردن یک بازیگر جدید و موقت در زمان اجرا دارید، میتوانید از این
mergeCasts
روش استفاده کنید. این تعاریف بازیگری به هر یک از بازیگرانی که قبلاً در مدل تعریف شده اند اضافه می شوند:
$user->mergeCasts([ 'is_admin' => 'integer', 'options' => 'object',]);
ویژگیهایی که هستند
null
پخش نمیشوند. علاوه بر این، هرگز نباید یک cast (یا یک ویژگی) که نام یک رابطه را دارد تعریف کنید یا یک cast را به کلید اصلی مدل اختصاص دهید.
ریخته گری رشته ای
می توانید از
Illuminate\Database\Eloquent\Casts\AsStringable
کلاس cast برای فرستادن یک ویژگی مدل به یک
شی
روان
Illuminate\Support\Stringable
استفاده کنید :
<?php namespace App\Models; use Illuminate\Database\Eloquent\Casts\AsStringable;use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * Get the attributes that should be cast. * * @return array<string, string> */ protected function casts(): array { return [ 'directory' => AsStringable::class, ]; }}
ارسال آرایه و JSON
بازیگران
array
به ویژه هنگام کار با ستون هایی که به صورت سریال JSON ذخیره می شوند مفید است. به عنوان مثال، اگر پایگاه داده شما دارای یک
JSON
یا
TEXT
نوع فیلد است که حاوی JSON سریالی است، افزودن
array
cast به آن ویژگی، هنگامی که در مدل Eloquent خود به آن دسترسی پیدا میکنید، به طور خودکار ویژگی را به یک آرایه PHP از فهرست خارج میکند:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * Get the attributes that should be cast. * * @return array<string, string> */ protected function casts(): array { return [ 'options' => 'array', ]; }}
هنگامی که cast تعریف شد، می توانید به
options
ویژگی دسترسی داشته باشید و به طور خودکار از JSON به یک آرایه PHP تبدیل می شود. وقتی مقدار مشخصه را تنظیم می کنید
options
، آرایه داده شده به طور خودکار برای ذخیره سازی به JSON تبدیل می شود:
use App\Models\User; $user = User::find(1); $options = $user->options; $options['key'] = 'value'; $user->options = $options; $user->save();
برای بهروزرسانی یک فیلد واحد از ویژگی JSON با نحو مختصرتر، میتوانید
ویژگی جرم را قابل تخصیص قرار دهید
و
->
هنگام فراخوانی
update
متد از عملگر استفاده کنید:
$user = User::find(1); $user->update(['options->key' => 'value']);
آرایه شیء و ریخته گری مجموعه
اگرچه قالب استاندارد
array
برای بسیاری از کاربردها کافی است، اما دارای معایبی است. از آنجایی که
array
cast یک نوع اولیه را برمی گرداند، امکان جهش مستقیم افست آرایه وجود ندارد. به عنوان مثال، کد زیر یک خطای PHP ایجاد می کند:
$user = User::find(1); $user->options['key'] = $value;
برای حل این مشکل، لاراول یک
AsArrayObject
cast ارائه می دهد که ویژگی JSON شما را به یک کلاس
ArrayObject
می فرستد . این ویژگی با استفاده از پیادهسازی
کست سفارشی
لاراول پیادهسازی میشود
، که به لاراول اجازه میدهد تا بهطور هوشمند شی جهشیافته را کش و تبدیل کند به طوری که ممکن است افستهای فردی بدون ایجاد خطای PHP اصلاح شوند. برای استفاده از
AsArrayObject
Cast، به سادگی آن را به یک ویژگی اختصاص دهید:
use Illuminate\Database\Eloquent\Casts\AsArrayObject; /** * Get the attributes that should be cast. * * @return array<string, string> */protected function casts(): array{ return [ 'options' => AsArrayObject::class, ];}
به طور مشابه، لاراول
AsCollection
بازیگری را ارائه میکند که ویژگی JSON شما را به نمونهای
از مجموعه
لاراول میفرستد :
use Illuminate\Database\Eloquent\Casts\AsCollection; /** * Get the attributes that should be cast. * * @return array<string, string> */protected function casts(): array{ return [ 'options' => AsCollection::class, ];}
اگر می خواهید
AsCollection
بازیگران به جای کلاس مجموعه پایه لاراول، یک کلاس مجموعه سفارشی را نمونه سازی کنند، می توانید نام کلاس مجموعه را به عنوان آرگومان cast ارائه کنید:
use App\Collections\OptionCollection;use Illuminate\Database\Eloquent\Casts\AsCollection; /** * Get the attributes that should be cast. * * @return array<string, string> */protected function casts(): array{ return [ 'options' => AsCollection::using(OptionCollection::class), ];}
ریخته گری تاریخ
created_at
بهطور پیشفرض، Eloquent ستونها و
updated_at
را به نمونههایی از
Carbon
میفرستد
، که کلاس PHP را گسترش میدهد
DateTime
و مجموعهای از روشهای مفید را ارائه میدهد. میتوانید با تعریف تاریخهای اضافی در روش مدل خود، ویژگیهای تاریخ اضافی را انتخاب کنید
casts
. به طور معمول، خرماها باید با استفاده از انواع ریخته گری ریخته
datetime
شوند
immutable_datetime
.
هنگام تعریف یک
date
یا
datetime
بازیگران، میتوانید قالب تاریخ را نیز مشخص کنید. این قالب زمانی استفاده خواهد شد که
مدل به یک آرایه یا JSON سریال شود
:
/** * Get the attributes that should be cast. * * @return array<string, string> */protected function casts(): array{ return [ 'created_at' => 'datetime:Y-m-d', ];}
هنگامی که یک ستون به عنوان تاریخ فرستاده می شود، می توانید مقدار ویژگی مدل مربوطه را به یک مهر زمانی یونیکس، رشته تاریخ (
Y-m-d
)، رشته تاریخ-زمان، یا یک
DateTime
نمونه تنظیم کنید
Carbon
. مقدار تاریخ به درستی تبدیل و در پایگاه داده شما ذخیره می شود.
می توانید با تعریف روشی
serializeDate
در مدل خود، قالب سریال سازی پیش فرض را برای تمام تاریخ های مدل خود سفارشی کنید. این روش بر نحوه قالب بندی تاریخ های شما برای ذخیره سازی در پایگاه داده تأثیر نمی گذارد:
/** * Prepare a date for array / JSON serialization. */protected function serializeDate(DateTimeInterface $date): string{ return $date->format('Y-m-d');}
برای مشخص کردن قالبی که باید هنگام ذخیره کردن تاریخ های یک مدل در پایگاه داده خود استفاده شود، باید یک
$dateFormat
ویژگی را در مدل خود تعریف کنید:
/** * The storage format of the model's date columns. * * @var string */protected $dateFormat = 'U';
ارسال تاریخ، سریالسازی و مناطق زمانی
بهطور پیشفرض،
date
و
datetime
ارسالها تاریخها را به رشته تاریخ UTC ISO-8601 ( )، بدون توجه به منطقه زمانی مشخصشده در
گزینه پیکربندی
YYYY-MM-DDTHH:MM:SS.uuuuuuZ
برنامهتان ، سریال میکنند.
timezone
شما قویاً تشویق میشوید همیشه از این قالب سریالسازی استفاده کنید، و همچنین با تغییر ندادن
timezone
گزینه پیکربندی برنامه خود از مقدار پیشفرض، تاریخهای برنامه خود را در منطقه زمانی UTC ذخیره کنید
UTC
. استفاده مداوم از منطقه زمانی UTC در سراسر برنامه، حداکثر سطح همکاری را با سایر کتابخانه های دستکاری تاریخ نوشته شده در PHP و جاوا اسکریپت فراهم می کند.
date
اگر یک قالب سفارشی برای پخش یا بازیگران
اعمال شود
datetime
، مانند
datetime:Y-m-d H:i:s
, منطقه زمانی داخلی نمونه کربن در طول سریالسازی تاریخ استفاده میشود. به طور معمول، این منطقه زمانی مشخص شده در
timezone
گزینه پیکربندی
برنامه شما خواهد بود .
Enum Casting
Eloquent همچنین به شما این امکان را می دهد که مقادیر ویژگی خود را به
Enums
PHP ارسال کنید . برای انجام این کار، میتوانید ویژگی و شمارهای را که میخواهید در
casts
متد مدل خود اعمال کنید، مشخص کنید:
use App\Enums\ServerStatus; /** * Get the attributes that should be cast. * * @return array<string, string> */protected function casts(): array{ return [ 'status' => ServerStatus::class, ];}
هنگامی که cast را روی مدل خود تعریف کردید، هنگامی که با ویژگی تعامل می کنید، ویژگی مشخص شده به طور خودکار به و از یک enum فرستاده می شود:
if ($server->status == ServerStatus::Provisioned) { $server->status = ServerStatus::Ready; $server->save();}
ریخته گری آرایه های Enums
گاهی اوقات ممکن است به مدل خود نیاز داشته باشید که آرایه ای از مقادیر enum را در یک ستون ذخیره کند. برای انجام این کار، می توانید از
AsEnumArrayObject
یا
AsEnumCollection
بازیگران ارائه شده توسط لاراول استفاده کنید:
use App\Enums\ServerStatus;use Illuminate\Database\Eloquent\Casts\AsEnumCollection; /** * Get the attributes that should be cast. * * @return array<string, string> */protected function casts(): array{ return [ 'statuses' => AsEnumCollection::of(ServerStatus::class), ];}
ارسال رمزگذاری شده
بازیگران
encrypted
مقدار ویژگی مدل را با استفاده از ویژگیهای
رمزگذاری
داخلی لاراول رمزگذاری میکنند . علاوه بر این
encrypted:array
،
encrypted:collection
,
encrypted:object
,
AsEncryptedArrayObject
, و
AsEncryptedCollection
بازیگران مانند همتایان رمزگذاری نشده خود کار می کنند. با این حال، همانطور که ممکن است انتظار داشته باشید، ارزش اساسی زمانی که در پایگاه داده شما ذخیره می شود رمزگذاری می شود.
از آنجایی که طول نهایی متن رمزگذاری شده قابل پیش بینی نیست و طولانی تر از متن ساده آن است، مطمئن شوید که ستون پایگاه داده مرتبط از
TEXT
نوع یا بزرگتر باشد. علاوه بر این، از آنجایی که مقادیر در پایگاه داده رمزگذاری شده اند، نمی توانید مقادیر ویژگی رمزگذاری شده را جستجو یا جستجو کنید.
چرخش کلید
همانطور که می دانید، لاراول رشته ها را با استفاده از
key
مقدار پیکربندی مشخص شده در فایل پیکربندی برنامه شما رمزگذاری می کند
app
. به طور معمول، این مقدار با مقدار
APP_KEY
متغیر محیطی مطابقت دارد. اگر نیاز دارید کلید رمزگذاری برنامه خود را بچرخانید، باید به صورت دستی ویژگی های رمزگذاری شده خود را با استفاده از کلید جدید رمزگذاری مجدد کنید.
ارسال زمان پرس و جو
گاهی اوقات ممکن است لازم باشد هنگام اجرای یک پرس و جو، از جمله زمانی که یک مقدار خام را از جدول انتخاب می کنید، Casts را اعمال کنید. به عنوان مثال، پرس و جو زیر را در نظر بگیرید:
use App\Models\Post;use App\Models\User; $users = User::select([ 'users.*', 'last_posted_at' => Post::selectRaw('MAX(created_at)') ->whereColumn('user_id', 'users.id')])->get();
ویژگی
last_posted_at
نتایج این پرس و جو یک رشته ساده خواهد بود. اگر بتوانیم
datetime
هنگام اجرای پرس و جو، یک cast برای این ویژگی اعمال کنیم، فوق العاده خواهد بود. خوشبختانه، ممکن است با استفاده از روش زیر این کار را انجام دهیم
withCasts
:
$users = User::select([ 'users.*', 'last_posted_at' => Post::selectRaw('MAX(created_at)') ->whereColumn('user_id', 'users.id')])->withCasts([ 'last_posted_at' => 'datetime'])->get();
بازیگران سفارشی
لاراول انواع مختلفی از بازیگران داخلی و مفید دارد. با این حال، ممکن است گاهی لازم باشد انواع بازیگران خود را تعریف کنید. برای ایجاد یک بازیگر،
make:cast
دستور Artisan را اجرا کنید. کلاس بازیگران جدید در
app/Casts
دایرکتوری شما قرار می گیرد:
php artisan make:cast Json
تمام کلاسهای کست سفارشی
CastsAttributes
رابط را پیادهسازی میکنند. کلاس هایی که این رابط را پیاده سازی می کنند باید a
get
و
set
متد را تعریف کنند. این
get
روش مسئول تبدیل یک مقدار خام از پایگاه داده به یک مقدار ریختهگری است، در حالی که
set
روش باید یک مقدار ریختهشده را به یک مقدار خام تبدیل کند که میتواند در پایگاه داده ذخیره شود. به عنوان مثال، نوع ریخته گری داخلی را
json
به عنوان یک نوع ریخته گری سفارشی دوباره پیاده سازی می کنیم:
<?php namespace App\Casts; use Illuminate\Contracts\Database\Eloquent\CastsAttributes;use Illuminate\Database\Eloquent\Model; class Json implements CastsAttributes{ /** * Cast the given value. * * @param array<string, mixed> $attributes * @return array<string, mixed> */ public function get(Model $model, string $key, mixed $value, array $attributes): array { return json_decode($value, true); } /** * Prepare the given value for storage. * * @param array<string, mixed> $attributes */ public function set(Model $model, string $key, mixed $value, array $attributes): string { return json_encode($value); }}
هنگامی که یک نوع Cast سفارشی را تعریف کردید، می توانید آن را با استفاده از نام کلاس آن به یک ویژگی مدل متصل کنید:
<?php namespace App\Models; use App\Casts\Json;use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * Get the attributes that should be cast. * * @return array<string, string> */ protected function casts(): array { return [ 'options' => Json::class, ]; }}
ارسال ارزش شی
شما محدود به ریختن مقادیر به انواع اولیه نیستید. همچنین می توانید مقادیری را به اشیا ارسال کنید. تعریف کستهای سفارشی که مقادیری را به اشیا میفرستند، بسیار شبیه ریختهگری به انواع اولیه است. با این حال،
set
روش باید آرایهای از جفتهای کلید/مقدار را برگرداند که برای تنظیم مقادیر خام و قابل ذخیرهسازی در مدل استفاده میشود.
به عنوان مثال، ما یک کلاس cast سفارشی تعریف می کنیم که چندین مقدار مدل را به یک
Address
شی مقدار واحد می ریزد. فرض می کنیم
Address
مقدار دارای دو ویژگی عمومی است:
lineOne
و
lineTwo
:
<?php namespace App\Casts; use App\ValueObjects\Address as AddressValueObject;use Illuminate\Contracts\Database\Eloquent\CastsAttributes;use Illuminate\Database\Eloquent\Model;use InvalidArgumentException; class Address implements CastsAttributes{ /** * Cast the given value. * * @param array<string, mixed> $attributes */ public function get(Model $model, string $key, mixed $value, array $attributes): AddressValueObject { return new AddressValueObject( $attributes['address_line_one'], $attributes['address_line_two'] ); } /** * Prepare the given value for storage. * * @param array<string, mixed> $attributes * @return array<string, string> */ public function set(Model $model, string $key, mixed $value, array $attributes): array { if (! $value instanceof AddressValueObject) { throw new InvalidArgumentException('The given value is not an Address instance.'); } return [ 'address_line_one' => $value->lineOne, 'address_line_two' => $value->lineTwo, ]; }}
هنگام ارسال به اشیاء ارزشی، هر تغییری که در شیء مقدار ایجاد شده باشد، قبل از ذخیره مدل، بهطور خودکار با مدل همگامسازی میشود:
use App\Models\User; $user = User::find(1); $user->address->lineOne = 'Updated Address Value'; $user->save();
اگر قصد دارید مدلهای Eloquent خود را که حاوی اشیاء ارزشی هستند به JSON یا آرایهها سریال کنید، باید واسطهای
Illuminate\Contracts\Support\Arrayable
andJsonSerializable
را روی شی مقدار پیادهسازی کنید.
مقدار ذخیره شی
هنگامی که ویژگی هایی که به اشیاء ارزشی داده می شوند حل و فصل می شوند، توسط Eloquent ذخیره می شوند. بنابراین، در صورت دسترسی مجدد به ویژگی، همان نمونه شی برگردانده می شود.
اگر میخواهید رفتار ذخیرهسازی شی در کلاسهای Cast سفارشی را غیرفعال کنید، میتوانید یک
withoutObjectCaching
ویژگی عمومی در کلاس Cast سفارشی خود اعلام کنید:
class Address implements CastsAttributes{ public bool $withoutObjectCaching = true; // ...}
سریال سازی آرایه / JSON
هنگامی که یک مدل Eloquent با استفاده از متدهای
toArray
و به
toJson
آرایه یا JSON تبدیل میشود، اشیاء با ارزش ریختهشده سفارشی شما معمولاً تا زمانی که واسطها
Illuminate\Contracts\Support\Arrayable
و را پیادهسازی میکنند، سریالسازی میشوند
JsonSerializable
. با این حال، هنگام استفاده از اشیاء ارزش ارائه شده توسط کتابخانه های شخص ثالث، ممکن است توانایی اضافه کردن این رابط ها به شی را نداشته باشید.
بنابراین، میتوانید تعیین کنید که کلاس cast سفارشی شما مسئول سریالسازی شی مقدار باشد. برای انجام این کار، کلاس cast سفارشی شما باید
Illuminate\Contracts\Database\Eloquent\SerializesCastableAttributes
رابط را پیاده سازی کند. این رابط بیان می کند که کلاس شما باید حاوی
serialize
متدی باشد که باید شکل سریالی شی مقدار شما را برگرداند:
/** * Get the serialized representation of the value. * * @param array<string, mixed> $attributes */public function serialize(Model $model, string $key, mixed $value, array $attributes): string{ return (string) $value;}
ریخته گری ورودی
گاهی اوقات، ممکن است نیاز داشته باشید که یک کلاس cast سفارشی بنویسید که فقط مقادیری را که روی مدل تنظیم میشوند تبدیل میکند و هیچ عملیاتی را هنگام بازیابی ویژگیها از مدل انجام نمیدهد.
کستهای سفارشی فقط ورودی باید
CastsInboundAttributes
رابط را پیادهسازی کنند، که فقط به یک
set
روش نیاز دارد تا تعریف شود. دستور Artisan ممکن است با
گزینه ای برای ایجاد یک کلاس cast فقط ورودی
make:cast
فراخوانی شود :
--inbound
php artisan make:cast Hash --inbound
یک نمونه کلاسیک از یک بازیگر فقط ورودی، یک بازیگر "هشینگ" است. به عنوان مثال، ما ممکن است یک بازیگر را تعریف کنیم که مقادیر ورودی را از طریق یک الگوریتم مشخص هش می کند:
<?php namespace App\Casts; use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;use Illuminate\Database\Eloquent\Model; class Hash implements CastsInboundAttributes{ /** * Create a new cast class instance. */ public function __construct( protected string|null $algorithm = null, ) {} /** * Prepare the given value for storage. * * @param array<string, mixed> $attributes */ public function set(Model $model, string $key, mixed $value, array $attributes): string { return is_null($this->algorithm) ? bcrypt($value) : hash($this->algorithm, $value); }}
پارامترهای بازیگری
هنگام پیوست کردن یک Cast سفارشی به یک مدل، پارامترهای Cast ممکن است با جدا کردن آنها از نام کلاس با استفاده از یک
:
کاراکتر و تعیین چند پارامتر با کاما مشخص شوند. پارامترها به سازنده کلاس cast ارسال می شود:
/** * Get the attributes that should be cast. * * @return array<string, string> */protected function casts(): array{ return [ 'secret' => Hash::class.':sha256', ];}
ریخته گری
ممکن است بخواهید به اشیاء ارزش برنامه خود اجازه دهید تا کلاس های Cast سفارشی خود را تعریف کنند. به جای اینکه کلاس cast سفارشی را به مدل خود وصل کنید، میتوانید یک کلاس شیء ارزش را که
Illuminate\Contracts\Database\Eloquent\Castable
رابط را پیادهسازی میکند، پیوست کنید:
use App\ValueObjects\Address; protected function casts(): array{ return [ 'address' => Address::class, ];}
اشیایی که
Castable
اینترفیس را پیاده سازی می کنند باید
castUsing
متدی را تعریف کنند که نام کلاس کلاس caster سفارشی که مسئول ارسال به کلاس و از
Castable
کلاس است را برمی گرداند:
<?php namespace App\ValueObjects; use Illuminate\Contracts\Database\Eloquent\Castable;use App\Casts\Address as AddressCast; class Address implements Castable{ /** * Get the name of the caster class to use when casting from / to this cast target. * * @param array<string, mixed> $arguments */ public static function castUsing(array $arguments): string { return AddressCast::class; }}
هنگام استفاده از
Castable
کلاسها، همچنان ممکن است آرگومانهایی در
casts
تعریف متد ارائه کنید. آرگومان ها به متد ارسال می شوند
castUsing
:
use App\ValueObjects\Address; protected function casts(): array{ return [ 'address' => Address::class.':argument', ];}
کلاسهای بازیگران Castable و ناشناس
با ترکیب «castables» با کلاسهای ناشناس
PHP
، میتوانید یک شی مقدار و منطق ریختهگری آن را بهعنوان یک شیء کستپذیر منفرد تعریف کنید. برای انجام این کار، یک کلاس ناشناس را از متد آبجکت مقدار خود برگردانید
castUsing
. کلاس ناشناس باید
CastsAttributes
اینترفیس را پیاده سازی کند:
<?php namespace App\ValueObjects; use Illuminate\Contracts\Database\Eloquent\Castable;use Illuminate\Contracts\Database\Eloquent\CastsAttributes; class Address implements Castable{ // ... /** * Get the caster class to use when casting from / to this cast target. * * @param array<string, mixed> $arguments */ public static function castUsing(array $arguments): CastsAttributes { return new class implements CastsAttributes { public function get(Model $model, string $key, mixed $value, array $attributes): Address { return new Address( $attributes['address_line_one'], $attributes['address_line_two'] ); } public function set(Model $model, string $key, mixed $value, array $attributes): array { return [ 'address_line_one' => $value->lineOne, 'address_line_two' => $value->lineTwo, ]; } }; }}