rdx/laravel-aggregate-relationships

在 Laravel 中实现 COUNT() 和 SUM() 等关系,无需使用 withCount()

1.8 2024-04-18 18:19 UTC

This package is auto-updated.

Last update: 2024-09-18 19:14:15 UTC


README

是什么? - Laravel 已经有关系了

Laravel 可以与其他模型建立关系,但不能与标量(例如数字)建立关系。此包可以 COUNT()SUM() 关系。特别是 COUNT() 非常有用,因为……

为什么? - Laravel 有这个功能!

不。在 Laravel 中,唯一计数关系的方法是使用 withCount(),但……

  • 只能用于 预加载,不能用于 懒加载
  • 不能在对象存在后,在集合上调用(如 ->load('name')
  • 总是命名为 {name}_count

如何实现?

将特性添加到您的模型/基础模型中

use RelatesToAggregates;

这会公开方法 hasCount(relatedClass, foreignKey)hasAggregate(relatedClass, aggregateColumn, foreignKey)hasManyScalar(targetKey, targetTable, foreignKey)

定义关系

class User extends Model {
	use RelatesToAggregates;

	// Number of transactions for this user
	function num_transactions() {
		return $this->hasCount(Transaction::class, 'user_id');
	}

	// Sum of all positive and negative transactions for this user
	function current_balance() {
		return $this->hasAggregate(Transaction::class, 'sum(money_change)', 'user_id');
	}

	// List of payment uuids
	function payment_refs() {
		return $this->hasManyScalar('reference_uuid', 'transactions', 'user_id');
	}
}

然后像正常关系一样预加载它

$users = User::with(['address', 'fav_color', 'num_transactions', 'current_balance', 'payment_refs'])->get();

或者以后,像正常关系一样,与 Laravel 的计数不同

$users = User::all();
$users->load(['address', 'fav_color', 'num_transactions', 'current_balance', 'payment_refs']);

如果不能/不想预加载它,则可以懒加载它,就像正常关系一样

$user = User::find(123);
echo "Balance: {$user->current_balance} ({$user->num_transactions} transactions): " .
	implode(', ', $user->payment_refs);

总结

  • 预加载和懒加载
  • 在现有集合上可预加载
  • 自定义名称

就像真实的关系一样!