Prologo
Primi Passi
Architettura
Le Basi
- Routing
- Middleware
- Protezione da CSRF
- Controller
- Richieste
- Risposte
- Views
- Blade
- Vite
- URL
- Sessioni
- Validazione
- Errori
- Logging
Approfondimenti
- Artisan
- Broadcasting
- Cache
- Collezioni
- Concorrenza
- Contesto
- Contratti
- Eventi
- File System
- Helpers
- Client HTTP
- Localizzazione
- Notifiche
- Sviluppo di Package
- Processi
- Code
- Rate-limiting
- Stringhe
- Scheduling di Task
Sicurezza
Database
Eloquent ORM
Testing
Package
Mutator e Cast
Introduzione
Accessors, mutators e attribute casting ti permettono di trasformare i valori degli attributi di Eloquent quando li recuperi o li imposti sulle istanze del modello. Ad esempio, potresti voler usare il Laravel encrypter per criptare un valore mentre è memorizzato nel database e poi decriptare automaticamente l’attributo quando lo accedi su un modello Eloquent. Oppure, potresti voler convertire una stringa JSON memorizzata nel tuo database in un array quando viene acceduta tramite il tuo modello Eloquent.
Accessors e Mutators
Definire un Accessor
Un accessor trasforma il valore di un attributo Eloquent quando viene accesso. Per definire un accessor, crea un metodo protetto nel tuo modello che rappresenta l’attributo accessibile. Il nome di questo metodo dovrebbe corrispondere alla rappresentazione in "camel case" del vero attributo del modello / colonna del database quando applicabile.
In questo esempio, definiamo un accessor per l’attributo first_name
. L’accessor verrà automaticamente chiamato da Eloquent quando si tenta di recuperare il valore dell’attributo first_name
. Tutti i metodi accessor / mutator degli attributi devono dichiarare un tipo di ritorno Illuminate\Database\Eloquent\Casts\Attribute
:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Ottieni il nome dell'utente.
*/
protected function firstName(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value),
);
}
}
Tutti i metodi accessor restituiscono un’istanza di Attribute
che definisce come l’attributo sarà accessibile e, opzionalmente, modificato. In questo esempio, definiamo solo come l’attributo sarà accessibile. Per farlo, forniamo l’argomento get
al costruttore della classe Attribute
.
Come puoi vedere, il valore originale della colonna viene passato all’accessor, permettendoti di manipolare e restituire il valore. Per accedere al valore dell’accessor, puoi semplicemente accedere all’attributo first_name
su un’istanza del modello:
use App\Models\User;
$user = User::find(1);
$firstName = $user->first_name;
Se desideri che questi valori calcolati vengano aggiunti alle rappresentazioni array / JSON del tuo modello, devi aggiungerli.
Creare Value Objects da più attributi
A volte il tuo accessor potrebbe aver bisogno di trasformare più attributi del modello in un unico "value object". Per fare ciò, la tua closure get
può accettare un secondo argomento $attributes
, che verrà fornito automaticamente alla closure e conterrà un array di tutti gli attributi correnti del modello:
use App\Support\Address;
use Illuminate\Database\Eloquent\Casts\Attribute;
/**
* Interagisce con l'indirizzo dell'utente.
*/
protected function address(): Attribute
{
return Attribute::make(
get: fn (mixed $value, array $attributes) => new Address(
$attributes['address_line_one'],
$attributes['address_line_two'],
),
);
}
Caching degli accessor
Quando si restituiscono value object dagli accessor, qualsiasi modifica apportata al value object verrà automaticamente sincronizzata con il modello prima che il modello venga salvato. Ciò è possibile perché Eloquent mantiene le istanze restituite dagli accessor in modo da poter restituire la stessa istanza ogni volta che l’accessor viene invocato:
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();
Tuttavia, potresti a volte voler abilitare il caching per valori primitivi come stringhe e booleani, in particolare se sono computazionalmente intensivi. Per ottenere ciò, puoi invocare il metodo shouldCache
quando definisci il tuo accessor:
protected function hash(): Attribute
{
return Attribute::make(
get: fn (string $value) => bcrypt(gzuncompress($value)),
)->shouldCache();
}
Se desideri disabilitare il comportamento di caching degli oggetti degli attributi, puoi invocare il metodo withoutObjectCaching
quando definisci l’attributo:
/**
* 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();
}
Definire un Mutator
Un mutator trasforma il valore di un attributo Eloquent quando viene impostato. Per definire un mutator, puoi fornire l’argomento set
quando definisci il tuo attributo. Definiamo un mutator per l’attributo first_name
. Questo mutator verrà chiamato automaticamente quando cerchiamo di impostare il valore dell’attributo first_name
sul modello:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Interagisci con il nome dell'utente.
*/
protected function firstName(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value),
set: fn (string $value) => strtolower($value),
);
}
}
La closure del mutator riceverà il valore che viene impostato sull’attributo, permettendoti di manipolare il valore e restituire il valore modificato. Per usare il nostro mutator, dobbiamo solo impostare l’attributo first_name
su un modello Eloquent:
use App\Models\User;
$user = User::find(1);
$user->first_name = 'Sally';
In questo esempio, il callback set
verrà chiamato con il valore Sally
. Il mutator applicherà la funzione strtolower
al nome e imposterà il valore risultante nell’array interno $attributes
del modello.
Mutare più attributi
A volte il tuo mutatore potrebbe dover impostare più attributi nel modello sottostante. Per farlo, puoi restituire un array dalla chiusura set
. Ogni chiave nell’array dovrebbe corrispondere a un attributo sottostante o a una colonna del database associata al modello:
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,
],
);
}
Conversione degli Attributi
La conversione degli attributi offre funzionalità simili agli accessors e mutators senza necessitare di definire metodi aggiuntivi nel tuo modello. Invece, il metodo casts
del tuo modello fornisce un modo comodo per convertire gli attributi in tipi di dati comuni.
Il metodo casts
dovrebbe restituire un array dove la chiave è il nome dell’attributo da convertire e il valore è il tipo a cui desideri convertire la colonna. I tipi di conversione supportati sono:
-
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
Per dimostrare la conversione degli attributi, convertiamo l’attributo is_admin
, che è memorizzato nel nostro database come intero (0
o 1
), in un valore booleano:
<?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',
];
}
}
Dopo aver definito la conversione, l’attributo is_admin
sarà sempre convertito in booleano quando lo accedi, anche se il valore sottostante è memorizzato nel database come intero:
$user = App\Models\User::find(1);
if ($user->is_admin) {
// ...
}
Se hai bisogno di aggiungere una nuova conversione temporanea durante l’esecuzione, puoi usare il metodo mergeCasts
. Queste definizioni di conversione saranno aggiunte a quelle già definite nel modello:
$user->mergeCasts([
'is_admin' => 'integer',
'options' => 'object',
]);
Gli attributi che sono
null
non verranno convertiti. Inoltre, non dovresti mai definire una conversione (o un attributo) che abbia lo stesso nome di una relazione o assegnare una conversione alla chiave primaria del modello.
Cast di Stringable
Puoi usare la classe di cast Illuminate\Database\Eloquent\Casts\AsStringable
per convertire un attributo del modello in un oggetto fluente Illuminate\Support\Stringable
:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\AsStringable;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Ottieni gli attributi che devono essere castati.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'directory' => AsStringable::class,
];
}
}
Casting Array e JSON
Il cast array
è particolarmente utile quando si lavora con colonne memorizzate come JSON serializzato. Ad esempio, se il tuo database ha un tipo di campo JSON
o TEXT
che contiene JSON serializzato, aggiungere il cast array
a quell’attributo deserializzerà automaticamente l’attributo in un array PHP quando lo accedi nel tuo modello Eloquent:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Ottieni gli attributi che devono essere castati.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'options' => 'array',
];
}
}
Una volta definito il cast, puoi accedere all’attributo options
e verrà automaticamente deserializzato da JSON in un array PHP. Quando imposti il valore dell’attributo options
, l’array fornito verrà automaticamente serializzato nuovamente in JSON per la memorizzazione:
use App\Models\User;
$user = User::find(1);
$options = $user->options;
$options['key'] = 'value';
$user->options = $options;
$user->save();
Per aggiornare un singolo campo di un attributo JSON con una sintassi più concisa, puoi rendere l’attributo assegnabile in massa e utilizzare l’operatore ->
quando chiami il metodo update
:
$user = User::find(1);
$user->update(['options->key' => 'value']);
Casting di Array Object e Collection
Anche se il cast standard array
è sufficiente per molte applicazioni, presenta alcuni svantaggi. Poiché il cast array
restituisce un tipo primitivo, non è possibile modificare direttamente un elemento dell’array. Ad esempio, il seguente codice genererà un errore PHP:
$user = User::find(1);
$user->options['key'] = $value;
Per risolvere questo problema, Laravel offre un cast AsArrayObject
che converte il tuo attributo JSON in una classe ArrayObject. Questa funzionalità è implementata utilizzando il custom cast di Laravel, che permette a Laravel di memorizzare nella cache e trasformare in modo intelligente l’oggetto modificato in modo tale che gli elementi individuali possano essere modificati senza generare un errore PHP. Per utilizzare il cast AsArrayObject
, assegnalo semplicemente a un attributo:
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,
];
}
In modo simile, Laravel offre un cast AsCollection
che converte il tuo attributo JSON in un’istanza Collection di Laravel:
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,
];
}
Se desideri che il cast AsCollection
istanzi una classe di collection personalizzata invece della classe di base di Laravel, puoi fornire il nome della classe di collection come argomento del 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),
];
}
Casting di Date
Di default, Eloquent convertirà le colonne created_at
e updated_at
in istanze di Carbon, che estende la classe PHP DateTime
e fornisce una serie di metodi utili. Puoi convertire ulteriori attributi di tipo data definendo casting aggiuntivi nel metodo casts
del tuo modello. Generalmente, le date dovrebbero essere convertite usando i tipi di casting datetime
o immutable_datetime
.
Quando definisci un casting date
o datetime
, puoi anche specificare il formato della data. Questo formato verrà usato quando il modello viene serializzato in un array o JSON:
/**
* Ottieni gli attributi che devono essere convertiti.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'created_at' => 'datetime:Y-m-d',
];
}
Quando una colonna è convertita in data, puoi impostare il valore dell’attributo corrispondente del modello su un timestamp UNIX, una stringa di data (Y-m-d
), una stringa di data-ora, o un’istanza di DateTime
/ Carbon
. Il valore della data verrà correttamente convertito e memorizzato nel tuo database.
Puoi personalizzare il formato di serializzazione predefinito per tutte le date del tuo modello definendo un metodo serializeDate
nel tuo modello. Questo metodo non influisce su come le date vengono formattate per l’archiviazione nel database:
/**
* Prepara una data per la serializzazione in array / JSON.
*/
protected function serializeDate(DateTimeInterface $date): string
{
return $date->format('Y-m-d');
}
Per specificare il formato che deve essere usato quando memorizzi effettivamente le date di un modello nel tuo database, dovresti definire la proprietà $dateFormat
nel tuo modello:
/**
* Il formato di archiviazione delle colonne data del modello.
*
* @var string
*/
protected $dateFormat = 'U';
Casting delle Date, Serializzazione e Fusi Orari
Per impostazione predefinita, i casting date
e datetime
serializzano le date in una stringa di data ISO-8601 UTC (YYYY-MM-DDTHH:MM:SS.uuuuuuZ
), indipendentemente dal fuso orario specificato nell’opzione di configurazione timezone
della tua applicazione. È fortemente consigliato utilizzare sempre questo formato di serializzazione e memorizzare le date della tua applicazione nel fuso orario UTC, mantenendo l’opzione di configurazione timezone
al valore predefinito UTC
. Usare costantemente il fuso orario UTC in tutta l’applicazione garantirà il massimo livello di interoperabilità con altre librerie di manipolazione delle date scritte in PHP e JavaScript.
Se viene applicato un formato personalizzato al casting date
o datetime
, come datetime:Y-m-d H:i:s
, verrà utilizzato il fuso orario interno dell’istanza Carbon durante la serializzazione della data. Di solito, questo sarà il fuso orario specificato nell’opzione di configurazione timezone
della tua applicazione. Tuttavia, è importante notare che le colonne timestamp
come created_at
e updated_at
sono esentate da questo comportamento e sono sempre formattate in UTC, indipendentemente dall’impostazione del fuso orario dell’applicazione.
Enum Casting
Eloquent permette anche di convertire i valori degli attributi in PHP Enums. Per fare ciò, puoi specificare l’attributo e l’enum che desideri convertire nel metodo casts
del tuo modello:
use App\Enums\ServerStatus;
/**
* Ottieni gli attributi che devono essere convertiti.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'status' => ServerStatus::class,
];
}
Una volta definita la conversione nel tuo modello, l’attributo specificato sarà automaticamente convertito in e da un enum quando interagisci con l’attributo:
if ($server->status == ServerStatus::Provisioned) {
$server->status = ServerStatus::Ready;
$server->save();
}
Casting di Array di Enum
A volte potresti aver bisogno che il tuo modello memorizzi un array di valori enum all’interno di una singola colonna. Per fare ciò, puoi utilizzare i cast AsEnumArrayObject
o AsEnumCollection
forniti da Laravel:
use App\Enums\ServerStatus;
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
/**
* Ottieni gli attributi che devono essere castati.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'statuses' => AsEnumCollection::of(ServerStatus::class),
];
}
Casting crittografato
Il cast encrypted
cripta il valore di un attributo del modello utilizzando le funzionalità di encryption integrate di Laravel. Inoltre, i cast encrypted:array
, encrypted:collection
, encrypted:object
, AsEncryptedArrayObject
e AsEncryptedCollection
funzionano come le loro controparti non criptate; tuttavia, come ci si può aspettare, il valore sottostante viene criptato quando viene memorizzato nel database.
Poiché la lunghezza finale del testo criptato non è prevedibile ed è più lunga del suo equivalente in testo semplice, assicurati che la colonna del database associata sia di tipo TEXT
o superiore. Inoltre, poiché i valori sono criptati nel database, non sarà possibile interrogare o cercare i valori degli attributi criptati.
Rotazione della Chiave
Come saprai, Laravel cripta le stringhe utilizzando il valore di configurazione key
specificato nel file di configurazione app
della tua applicazione. Tipicamente, questo valore corrisponde al valore della variabile d’ambiente APP_KEY
. Se hai bisogno di ruotare la chiave di crittografia della tua applicazione, dovrai re-crittografare manualmente i tuoi attributi criptati usando la nuova chiave.
Casting al Tempo della Query
A volte potresti aver bisogno di applicare dei cast durante l’esecuzione di una query, ad esempio quando selezioni un valore grezzo da una tabella. Per esempio, considera la seguente query:
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();
L’attributo last_posted_at
nei risultati di questa query sarà una semplice stringa. Sarebbe ottimo se potessimo applicare un cast datetime
a questo attributo durante l’esecuzione della query. Per fortuna, possiamo ottenere questo usando il metodo withCasts
:
$users = User::select([
'users.*',
'last_posted_at' => Post::selectRaw('MAX(created_at)')
->whereColumn('user_id', 'users.id')
])->withCasts([
'last_posted_at' => 'datetime'
])->get();
Cast Personalizzati
Laravel offre una varietà di tipi di cast integrati e utili; tuttavia, a volte potresti dover definire i tuoi tipi di cast personalizzati. Per creare un cast, esegui il comando Artisan make:cast
. La nuova classe di cast verrà posizionata nella directory app/Casts
:
php artisan make:cast Json
Tutte le classi di cast personalizzate implementano l’interfaccia CastsAttributes
. Le classi che implementano questa interfaccia devono definire un metodo get
e un metodo set
. Il metodo get
è responsabile della trasformazione di un valore grezzo dal database in un valore castato, mentre il metodo set
deve trasformare un valore castato in un valore grezzo che può essere memorizzato nel database. Ad esempio, reimplementeremo il tipo di cast integrato json
come tipo di cast personalizzato:
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
class Json implements CastsAttributes
{
/**
* Effettua il cast del valore dato.
*
* @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);
}
/**
* Prepara il valore dato per l'archiviazione.
*
* @param array<string, mixed> $attributes
*/
public function set(Model $model, string $key, mixed $value, array $attributes): string
{
return json_encode($value);
}
}
Una volta definito un tipo di cast personalizzato, puoi assegnarlo a un attributo del modello utilizzando il nome della sua classe:
<?php
namespace App\Models;
use App\Casts\Json;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Ottieni gli attributi che devono essere castati.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'options' => Json::class,
];
}
}
Casting dei Value Object
Non sei limitato a convertire i valori in tipi primitivi. Puoi anche convertire i valori in oggetti. Definire cast personalizzati che trasformano i valori in oggetti è molto simile al cast in tipi primitivi; tuttavia, il metodo set
dovrebbe restituire un array di coppie chiave/valore che verranno utilizzate per impostare valori grezzi e memorizzabili sul modello.
Come esempio, definiremo una classe di cast personalizzata che converte più valori del modello in un unico value object Address
. Supponiamo che il valore Address
abbia due proprietà pubbliche: lineOne
e 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,
];
}
}
Quando si effettua il cast in value object, eventuali modifiche apportate al value object verranno automaticamente sincronizzate con il modello prima che il modello venga salvato:
use App\Models\User;
$user = User::find(1);
$user->address->lineOne = 'Updated Address Value';
$user->save();
Se prevedi di serializzare i tuoi modelli Eloquent contenenti value object in JSON o array, dovresti implementare le interfacce
Illuminate\Contracts\Support\Arrayable
eJsonSerializable
sul value object.
Cache dei Value Object
Quando gli attributi convertiti in value object vengono risolti, vengono memorizzati nella cache da Eloquent. Pertanto, verrà restituita la stessa istanza dell’oggetto se l’attributo viene nuovamente accesso.
Se desideri disabilitare il comportamento di caching degli oggetti nelle classi di cast personalizzate, puoi dichiarare una proprietà pubblica withoutObjectCaching
nella tua classe di cast personalizzata:
class Address implements CastsAttributes
{
public bool $withoutObjectCaching = true;
// ...
}
Serializzazione in Array / JSON
Quando un modello Eloquent viene convertito in un array o in JSON utilizzando i metodi toArray
e toJson
, i tuoi value object con cast personalizzati saranno tipicamente serializzati, a condizione che implementino le interfacce Illuminate\Contracts\Support\Arrayable
e JsonSerializable
. Tuttavia, quando si utilizzano value object forniti da librerie di terze parti, potresti non poter aggiungere queste interfacce all’oggetto.
Pertanto, puoi specificare che la tua classe di cast personalizzata sarà responsabile della serializzazione del value object. Per fare ciò, la tua classe di cast personalizzata dovrebbe implementare l’interfaccia Illuminate\Contracts\Database\Eloquent\SerializesCastableAttributes
. Questa interfaccia richiede che la tua classe contenga un metodo serialize
che restituisca la forma serializzata del tuo value object:
/**
* Ottieni la rappresentazione serializzata del valore.
*
* @param array<string, mixed> $attributes
*/
public function serialize(Model $model, string $key, mixed $value, array $attributes): string
{
return (string) $value;
}
Casting Inbound
Occasionalmente, potresti aver bisogno di scrivere una classe di cast personalizzata che trasforma solo i valori che vengono impostati sul modello e non esegue operazioni quando gli attributi vengono recuperati dal modello.
I cast personalizzati solo inbound dovrebbero implementare l’interfaccia CastsInboundAttributes
, che richiede solo la definizione del metodo set
. Il comando Artisan make:cast
può essere invocato con l’opzione --inbound
per generare una classe di cast solo inbound:
php artisan make:cast Hash --inbound
Un esempio classico di cast solo inbound è un cast di "hashing". Ad esempio, possiamo definire un cast che esegue l’hash dei valori inbound tramite un algoritmo dato:
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;
use Illuminate\Database\Eloquent\Model;
class Hash implements CastsInboundAttributes
{
/**
* Crea una nuova istanza della classe di cast.
*/
public function __construct(
protected string|null $algorithm = null,
) {}
/**
* Prepara il valore dato per l'archiviazione.
*
* @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);
}
}
Parametri di Cast
Quando si assegna un cast personalizzato a un modello, i parametri del cast possono essere specificati separandoli dal nome della classe utilizzando il carattere :
e delimitando più parametri con una virgola. I parametri verranno passati al costruttore della classe cast:
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'secret' => Hash::class.':sha256',
];
}
Castables
Potresti voler permettere ai value object della tua applicazione di definire le proprie classi di cast personalizzate. Invece di allegare la classe di cast personalizzata al tuo modello, puoi alternativamente allegare una classe di value object che implementa l’interfaccia Illuminate\Contracts\Database\Eloquent\Castable
:
use App\ValueObjects\Address;
protected function casts(): array
{
return [
'address' => Address::class,
];
}
Gli oggetti che implementano l’interfaccia Castable
devono definire un metodo castUsing
che ritorna il nome della classe caster personalizzata responsabile del cast da e verso la classe Castable
:
<?php
namespace App\ValueObjects;
use Illuminate\Contracts\Database\Eloquent\Castable;
use App\Casts\Address as AddressCast;
class Address implements Castable
{
/**
* Ottieni il nome della classe caster da usare quando si effettua il cast da / a questo target di cast.
*
* @param array<string, mixed> $arguments
*/
public static function castUsing(array $arguments): string
{
return AddressCast::class;
}
}
Quando usi le classi Castable
, puoi comunque fornire argomenti nella definizione del metodo casts
. Gli argomenti saranno passati al metodo castUsing
:
use App\ValueObjects\Address;
protected function casts(): array
{
return [
'address' => Address::class.':argument',
];
}
Castables & Classi Cast Anonime
Combinando i "castables" con le classi anonime di PHP, puoi definire un value object e la sua logica di casting come un unico oggetto castable. Per fare ciò, restituisci una classe anonima dal metodo castUsing
del tuo value object. La classe anonima deve implementare l’interfaccia CastsAttributes
:
<?php
namespace App\ValueObjects;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class Address implements Castable
{
// ...
/**
* Ottieni la classe caster da usare quando si effettua il casting da / verso questo target di cast.
*
* @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,
];
}
};
}
}