我有一个与 Section 模型相关联的帖子模型,这取决于额外的工作条件:
<?php
class Post extends Base
{
public function section()
{
return $this->belongsTo('App\Models\Section', 'id_cat')->where('website', $this->website);
}
}
当我想要检索帖子并获取它的关联部分时,我可以这样做:
$post = Post::first();
echo $post->section->name; // Output the section's name
但是,当尝试使用急切加载来获取该部分时:
Post::with(['section'])->chunk(1000, function ($posts) {
echo $post->section->name;
});
Laravel抛出以下异常:
PHP error: Trying to get property of non-object
当我对上面的热切加载查询返回的Post对象进行调试时,我注意到section
关系是null
。
请注意,如果我从belongsTo
关联中删除条件,它工作正常。
你们有没有想过为什么会这样?
答案 0 :(得分:1)
正如我的评论中所提到的,func updateMapForCoordinate(coordinate: CLLocationCoordinate2D) {
let camera = MKMapCamera(lookingAtCenterCoordinate: coordinate, fromDistance: 1000, pitch: 0, heading: 0)
mapView.setCamera(camera, animated: false)
var center = coordinate;
center.latitude -= self.mapView.region.span.latitudeDelta / 6.0;
mapView.setCenterCoordinate(center, animated: false);
}
不应该用在关系定义中。因此,您的关系定义仅适用于
where
你可以用这种方式急切加载(不用chunk等给出确切的查询)
public function section()
{
return $this->belongsTo('App\Models\Section', 'id_cat');
}
即。当你在请求中传递变量Post::with(['section' => function ($query) use ($request) {
$query->where('website', $request['website'])
}])->get()->first();
或者以类似的方式使用任何其他变量时。
我希望这可以解释。如果有任何不清楚的地方,请添加评论。
答案 1 :(得分:0)
您可以通过定义自定义关系来实现它。
BelongsToWith.php
<?php
declare(strict_types=1);
namespace App\Database\Eloquent\Relations;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class BelongsToWith extends BelongsTo
{
/**
* @var array [$foreignColumn => $ownerColumn, ...] assoc or [$column, ...] array
*/
protected $conditions = [];
public function __construct(array $conditions, Builder $query, Model $child, string $foreignKey, string $ownerKey, string $relation)
{
$this->conditions = $conditions;
parent::__construct($query, $child, $foreignKey, $ownerKey, $relation);
}
public function addConstraints()
{
if (static::$constraints) {
// Add base constraints
parent::addConstraints();
// Add extra constraints
foreach ($this->conditions as $key => $value) {
if (is_int($key)) {
$key = $value;
}
$this->getQuery()->where($this->related->getTable() . '.' . $value, '=', $this->child->{$key});
}
}
}
public function addEagerConstraints(array $models)
{
// Ignore empty models
if ([null] === $this->getEagerModelKeys($models)) {
parent::addEagerConstraints($models);
return;
}
$this->getQuery()->where(function (Builder $query) use ($models) {
foreach ($models as $model) {
$query->orWhere(function (Builder $query) use ($model) {
// Add base constraints
$query->where($this->related->getTable() . '.' . $this->ownerKey, $model->getAttribute($this->foreignKey));
// Add extra constraints
foreach ($this->conditions as $key => $value) {
if (is_int($key)) {
$key = $value;
}
$query->where($this->related->getTable() . '.' . $value, $model->getAttribute($key));
}
});
}
});
}
public function match(array $models, Collection $results, $relation)
{
$dictionary = [];
foreach ($results as $result) {
// Base constraints
$keys = [$result->getAttribute($this->ownerKey)];
// Extra constraints
foreach ($this->conditions as $key => $value) {
$keys[] = $result->getAttribute($value);
}
// Build nested dictionary
$current = &$dictionary;
foreach ($keys as $key) {
$current = &$current[$key];
}
$current = $result;
unset($current);
}
foreach ($models as $model) {
$current = $dictionary;
// Base constraints
if (!isset($current[$model->{$this->foreignKey}])) {
continue;
}
$current = $current[$model->{$this->foreignKey}];
// Extra constraints
foreach ($this->conditions as $key => $value) {
if (is_int($key)) {
$key = $value;
}
if (!isset($current[$model->{$key}])) {
continue 2;
}
$current = $current[$model->{$key}];
}
// Set passed result
$model->setRelation($relation, $current);
}
return $models;
}
}
HasExtendedRelationships.php
<?php
declare(strict_types=1);
namespace App\Database\Eloquent\Concerns;
use App\Database\Eloquent\Relations\BelongsToWith;
use Illuminate\Support\Str;
trait HasExtendedRelationships
{
public function belongsToWith(array $conditions, $related, $foreignKey = null, $ownerKey = null, $relation = null): BelongsToWith
{
if ($relation === null) {
$relation = $this->guessBelongsToRelation();
}
$instance = $this->newRelatedInstance($related);
if ($foreignKey === null) {
$foreignKey = Str::snake($relation) . '_' . $instance->getKeyName();
}
$ownerKey = $ownerKey ?: $instance->getKeyName();
return new BelongsToWith($conditions, $instance->newQuery(), $this, $foreignKey, $ownerKey, $relation);
}
}
然后:
class Post extends Base
{
use HasExtendedRelationships;
public function section(): BelongsToWith
{
return $this->belongsToWith(['website'], App\Models\Section::class, 'id_cat');
}
}
$posts = Post::with('section')->find([1, 2]);
您的预先加载查询将如下:
select * from `sections`
where (
(
`sections`.`id` = {$posts[0]->id_cat}
and `sections`.`website` = {$posts[0]->website}
)
or
(
`sections`.`id` = {$posts[1]->id_cat}
and `sections`.`website` = {$posts[1]->website}
)
)