-
-
Notifications
You must be signed in to change notification settings - Fork 142
Mappable
Define mappings on the protected $maps
variable like bellow. Use this extension in order to map your 1-1 relations (BelongsTo
, HasOne
, MorphOne
and MorphTo
) AND/OR simple column aliasing (eg. if you work with legacy DB with fields like FIELD_01
or somereallyBad_and_long_name
- inspired by @treythomas123)
<?php namespace App;
use Sofa\Eloquence\Eloquence; // base trait
use Sofa\Eloquence\Mappable; // extension trait
class User extends \Eloquent {
use Eloquence, Mappable;
protected $maps = [
// implicit relation mapping:
'profile' => ['first_name', 'last_name'],
// explicit relation mapping:
'picture' => 'profile.picture_path',
// simple alias
'dev_friendly_name' => 'badlynamedcolumn',
];
public function profile()
{
return $this->belongsTo(Profile::class); // *
}
-
::class
is PHP5.5 constant, in PHP5.4 use full namespaced string instead.
You can also add mapped attributes to the array representation of your model, just like any accessor:
protected $maps = [
'picture' => 'profile.picture_path'
];
protected $appends = ['picture'];
You can get, as well as set, mapped attributes:
$user->profile->first_name; // 'Jarek Tkaczyk'
$user->first_name = 'John Doe';
$user->profile->first_name; // 'John Doe'
// mapped models are saved automatically for you:
$user->save();
You can also query the mappings:
// simple alias
User::where('dev_friendly_name', 'some_value')->toSql();
// select * from users where badlynamedcolumn = 'some_value'
// relation mapping
User::where('first_name', 'Romain Lanz')->toSql(); // uses whereHas
// select * from users where (
// select count(*) from profiles
// where users.profile_id = profiles.id and first_name = 'Romain Lanz'
// ) >= 1
// Order by related field
User::orderBy('first_name')->toSql(); // uses joins
// select users.* from users
// left join profiles on users.profile_id = profiles.id
// order by profiles.first_name asc
User::latest('users.created_at')->pluck('first_name'); // uses joins
// 'Romain Lanz'
Note that MorphTo
mapping doesn't support join-based querying (orderBy
, pluck
and aggregates
).
Mappable
offers 2 ways of defining mappings for your convenience.
Let's compare equivalent mappings:
// Assuming User belongsTo Profile
// and Profile hasOne Picture
// profiles table: id, first_name, last_name
// pictures table: id, profile_id, path
// User model
// explicit
protected $maps = [
'first_name' => 'profile.first_name', // $user->first_name
'last_name' => 'profile.last_name', // $user->last_name
'picture_path' => 'profile.picture.path', // $user->picture_path
];
// implicit
protected $maps = [
'profile' => ['first_name', 'last_name'], // $user->first_name / ->last_name
'profile.picture' => ['path'], // $user->path
];
As you can notice, behaviour is just the same. However, there is slight difference - explicit mapping offers more flexibility, in that you can define custom key for mapped value (picture_path
), while with implicit mapping you have to use real attribute name defined in the related model (path
).
Mappings work also with form model binding.
Important: Mind that each mapping call requires the relation to be loaded, so you may need to use eager loading in order to avoid n+1 query issue. However if you query mapped attributes, the relation is automatically eager loaded for you.