worksome / model-attributes
Model attributes are dynamically generated data on models added as a relationship.
Installs: 250 512
Dependents: 0
Suggesters: 0
Security: 0
Stars: 4
Watchers: 9
Forks: 1
Open Issues: 0
Requires
- php: ^8.2
- illuminate/contracts: ^9.46|^10.0
- spatie/laravel-package-tools: ^1.14.1
Requires (Dev)
- nunomaduro/collision: ^6.2
- nunomaduro/larastan: ^2.3
- orchestra/testbench: ^7.18|^8.0
- pestphp/pest: ^1.22.3
- pestphp/pest-plugin-laravel: ^1.4
- pestphp/pest-plugin-parallel: ^1.1
- worksome/coding-style: ^2.3
README
Model attributes are dynamically generated values for models. They are used as eloquent relationships which can be eager loaded.
Installation
You can install the package via composer:
composer require worksome/model-attributes
Usage
Assuming we have the following table structure:
users:
- id
reviews:
- id
- user_id
- stars
And the following models:
class User extends Model
{
public function reviews()
{
$this->hasMany(Review::class);
}
}
class Review extends Model
{
public function user()
{
$this->belongsTo(User::class);
}
}
We can add a rating
property to each user that is the calculated average of a users reviews. First we're going to create a Model attribute:
class Rating extends \Worksome\ModelAttributes\ModelAttribute
{
protected $casts = [
'id' => 'int',
'user_id' => 'int',
'rating' => 'float',
];
public static function attributeGlobalScope(Builder $query): void
{
$ratingModel = new Rating();
$query
->groupBy($ratingModel->user()->getForeignKeyName())
->addSelect([
$ratingModel->getKeyName(), // id
$ratingModel->user()->getForeignKeyName(), // user_id
\DB::raw('avg(stars) as rating'), // rating
]);
}
}
and add it as a relationship to the user model
public function rating(): \Worksome\ModelAttributes\AttributeRelation|\Illuminate\Database\Eloquent\Relations\HasOne
{
return new \Worksome\ModelAttributes\AttributeRelation(
$this->hasOne(Rating::class)
);
}
So that it can be used like so:
$user = User::first();
$rating = $user->rating; // The rating model attribute created above
$rating->rating // the actual rating
Since model attributes are essentially dynamically generated data, and the rating is a scalar, we can override the getValue()
method of a model in order to "reach" the rating faster:
public function getValue()
{
return $this->rating;
}
And now the rating can be accessed like so:
User::first()->rating;
And because it's a relationship it can be eager loaded:
User::with('rating')->get()->map->rating;
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
License
The MIT License (MIT). Please see License File for more information.