Laravel - Eloquent - 获得没有外键的关系
Posted
技术标签:
【中文标题】Laravel - Eloquent - 获得没有外键的关系【英文标题】:Laravel - Eloquent - Get a ralationship without foreign key 【发布时间】:2021-10-29 07:26:41 【问题描述】:我正在做一个 Laravel 项目,我有模型“预订”和“周”。
型号“Week”有开始日期和价格,型号“Reservation”有开始日期和结束日期。
我希望能够像这样做一个有说服力的选择:Reservation::with('weeks')->get()
,但是如果我在 eloquent 以下做一些事情,就不会将其识别为关系,并且我不能在 Reservation 模型中使用“HasMany”,因为我不要将表格与 id 相关联,而仅与日期相关联。
我怎样才能获得一段关系的周数?
class Reservation extends Model
public function weeks()
return Week::whereDate('starting_date', '>=', $this->starting_date)
->whereDate('starting_date', '<', $this->ending_date)
->orderBy('starting_date')
->get();
已编辑:感谢@Tim Lewis
【问题讨论】:
Reservation::all()->with('weeks')
不行; ::all()
转换为没有 with()
方法的 Collection。请改用Reservation::with('weeks')->get()
。但是,如果你不能定义关系,那也行不通。您不能急于加载 weeks
(with('weeks')
),因为它不会返回关系。
【参考方案1】:
感谢这个存储库,我终于成功了:https://github.com/johnnyfreeman/laravel-custom-relation
存储库已存档,无法为 Laravel 8 安装,所以我只是复制了此文件夹中的文件:
app\Relations\Custom.php app\Traits\HasCustomRelations.php这允许我使用带有前缘约束的Reservation::with('weeks')->get();
use App\Models\Week;
use App\Traits\HasCustomRelations;
class Reservation extends Model
use HasCustomRelations;
public function weeks()
return $this->custom(
Week::class,
// add constraints
function ($relation)
if($this->starting_date && $this->ending_date)
$relation->getQuery()
->where('weeks.starting_date', '>=', $this->starting_date)
->where('weeks.starting_date', '<', $this->ending_date);
else
$relation->getQuery();
,
// add eager constraints
function ($relation, $models)
$starting_date = $models[0]->starting_date;
$ending_date = $models[count($models)-1]->ending_date;
$relation->getQuery()
->where('weeks.starting_date', '>=', $starting_date)
->where('weeks.starting_date', '<', $ending_date);
,
// add eager matcher
function ($models, $results, $foreignTable, $relation)
foreach ($models as $model)
$model->setRelation($foreignTable, $results
->where('starting_date', '>=', $model->starting_date)
->where('starting_date', '<', $model->ending_date));
return $models;
);
【讨论】:
【参考方案2】:你快到了。只需使用访问器来获取周数:
public function getWeeksAttribute()
return Week::whereDate('starting_date', '>=', $this->starting_date)
->whereDate('starting_date', '<', $this->ending_date)
->orderBy('starting_date')
->get();
您将能够像获取任何其他属性一样获取周数。如果您需要将模型序列化为 Json,请记住将 weeks
添加到模型中的 $appends
array 中。
【讨论】:
谢谢,如果我这样做,这项工作:Reservation::first()->weeks 但如果我这样做:Reservation::with('weeks')->first()我收到此错误:调用模型 [App\Models\Reservation] 上的未定义关系 [weeks]。 您不要使用“with”,因为这是一个访问者,而不是关系。由于您的两个表中的任何一个都没有外键,因此不可能建立真正的关系。我相信这是下一个最佳解决方案。 访问器也可以在模型中不指定 $appends 的情况下工作,但使用 Reservation::first()->append('weeks'),但我想要做的是 ->with('weeks' ) 进行查询优化。如果我选择更多保留,则使用访问器,append 方法会为每个模型执行查询。对我来说最好的解决方案可能是没有foreign_key的“HasMany”关系,但我不知道该怎么做以上是关于Laravel - Eloquent - 获得没有外键的关系的主要内容,如果未能解决你的问题,请参考以下文章
Laravel,获得类似 Eloquent 使用查询生成器的结果