n7olkachev / laravel-computed-properties
Computed properties for Eloquent
Installs: 605
Dependents: 0
Suggesters: 0
Security: 0
Stars: 192
Watchers: 6
Forks: 9
Open Issues: 0
Requires
- php: ^7.0
- illuminate/config: ~5.4.0|~5.5.0|~5.6.0|~5.7.0
- illuminate/database: ~5.4.0|~5.5.0|~5.6.0|~5.7.0
- illuminate/support: ~5.4.0|~5.5.0|~5.6.0|~5.7.0
Requires (Dev)
- orchestra/database: ~3.3.0|~3.4.0
- orchestra/testbench: ~3.3.0|~3.4.0
- phpunit/phpunit: ^5.7
README
Laravel 5.4+
Based on this tweet: https://twitter.com/reinink/status/899713609722449920
Some examples for better understanding of this power:
class Order extends Model { use ComputedProperties; public function products() { return $this->hasMany(OrderProduct::class); } public function computedSum($order) { return OrderProduct::select(new Expression('sum(price * count)')) ->where('order_id', $order->id); } }
Now, we can get order sum with $order->sum
. Yep, we can get this functionality with getSumAttribute
but wait! The real power of this package is that we can use this method inside our queries:
$orders = Order::withComputed('sum')->get()
We eager loaded sum
attribute without N+1
problem.
But there is more! You can add having
or orderBy
clauses to such queries for filtering and sorting!
Order::withComputed('sum')->orderBy('sum', 'desc')->get()
Installation
You can install the package via composer:
composer require n7olkachev/laravel-computed-properties
Next, add ComputedProperties trait to your models:
use ComputedProperties;
That's all!
More examples
class Page extends Model { use ComputedProperties; public $timestamps = false; protected $casts = [ 'last_view' => 'datetime', 'first_view' => 'datetime', ]; public function computedLastView($page) { return PageView::select(new Expression('max(viewed_at)')) ->where('page_id', $page->id); } public function computedFirstView($page) { return PageView::select(new Expression('min(viewed_at)')) ->where('page_id', $page->id); } }
We can find Page
by its first view:
$page = Page::withComputed('first_view') ->having('first_view', Carbon::create(2017, 8, 16, 0, 0, 0)) ->first();
Or by both first_view
and last_view
$page = Page::withComputed(['first_view', 'last_view']) ->having('first_view', Carbon::create(2017, 8, 16, 0, 0, 0)) ->having('last_view', Carbon::create(2017, 8, 21, 0, 0, 0)) ->first();
We can order pages by theirs last_view
$pages = Page::withComputed('last_view') ->orderBy('last_view', 'desc') ->get()
Testing
$ composer test
Credits
- Jonathan Reinink (idea)
- Nikita Tolkachev
Sponsored by
Web agency based in Minsk, Belarus
License
The MIT License (MIT)