I know it's possible to define accessors and mutators for individual fields, like so:
public function setSomeAttribute($value) {
// set the attribute
}
public function getSomeAttribute() {
// return the attribute}
}
But is it possible to define a fallback method that will be used for all attribute gets and sets?
The reason being that I want to convert any empty values to null values on the fly, to keep my database clean and allow nullable fields to be null instead of an empty string (if there's a better way to do this let me know!)
I'm looking for something like
public function setAttribute($property,$value) {
$this->$property = empty($value) ? null : $value;
}
UPDATE:
Thanks to Chris Goosey I've found a solution that works for me. I extended the Eloquent model method setAttribute, and I set the value to the column default if it's empty. That's usually null, zero or an empty string in my databases so works for me!
public function setAttribute($key, $value)
{
// Convert empty values to their default values (e.g. null, zero)
if(empty($value) && $this->getSchema()->hasColumn($key)) {
$value = $this->getSchema()->getColumn($key)->getDefault();
}
parent::setAttribute($key,$value);
}
Accessors and mutators allow you to format Eloquent attributes when retrieving them from a model or setting their value. For example, you may want to use the Laravel encrypter to encrypt a value while it is stored in the database, and then automatically decrypt the attribute when you access it on an Eloquent model.
Laravel accessors and mutators are custom, user defined methods that allow you to format Eloquent attributes. Accessors are used to format attributes when you retrieve them from the database, while mutators format the attributes before saving them to the database.
Casting a value means changing it to (or ensuring it is already) a particular type. Some types you might be familiar with are Integer or Boolean . Simply put, type casting is a method of changing an entity from one data type to another.
Defining A Mutator The mutator closure will receive the value that is being set on the attribute, allowing you to manipulate the value and return the manipulated value. To use our mutator, we only need to set the first_name attribute on an Eloquent model: use App\Models\User; $user = User::find(1);
Best way is probably to extend the Eloquent class overwriting the setAttribute and getAttribute methods.
For all your models to inherit these overwritten methods you would want to create a class that extends eloquent e.g.
<?php
class BaseModel extends eloquent {
public function setAttribute($property,$value) {
$this->$property = empty($value) ? null : $value;
}
public function getAttribute($key) {
// Do Stuff
}
}
and then all your models should extend from this new class, e.g.
<?php
class User extends BaseModel {
protected $table = 'users';
}
It is also worth mentioning your new methods should have all the functionality of the old method plus your new functionality, this is what the getAttribute() looks like (Illuminate\Database\Eloquent line 2212):
/**
* Get an attribute from the model.
*
* @param string $key
* @return mixed
*/
public function getAttribute($key)
{
$inAttributes = array_key_exists($key, $this->attributes);
// If the key references an attribute, we can just go ahead and return the
// plain attribute value from the model. This allows every attribute to
// be dynamically accessed through the _get method without accessors.
if ($inAttributes || $this->hasGetMutator($key))
{
return $this->getAttributeValue($key);
}
// If the key already exists in the relationships array, it just means the
// relationship has already been loaded, so we'll just return it out of
// here because there is no need to query within the relations twice.
if (array_key_exists($key, $this->relations))
{
return $this->relations[$key];
}
// If the "attribute" exists as a method on the model, we will just assume
// it is a relationship and will load and return results from the query
// and hydrate the relationship's value on the "relationships" array.
$camelKey = camel_case($key);
if (method_exists($this, $camelKey))
{
return $this->getRelationshipFromMethod($key, $camelKey);
}
}
and the setAttribute in the same file looks like this (line 2338):
/**
* Set a given attribute on the model.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function setAttribute($key, $value)
{
// First we will check for the presence of a mutator for the set operation
// which simply lets the developers tweak the attribute as it is set on
// the model, such as "json_encoding" an listing of data for storage.
if ($this->hasSetMutator($key))
{
$method = 'set'.studly_case($key).'Attribute';
return $this->{$method}($value);
}
// If an attribute is listed as a "date", we'll convert it from a DateTime
// instance into a form proper for storage on the database tables using
// the connection grammar's date format. We will auto set the values.
elseif (in_array($key, $this->getDates()))
{
if ($value)
{
$value = $this->fromDateTime($value);
}
}
$this->attributes[$key] = $value;
}
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With