0
votes

i have made indirect relation from one model to another in couple of my models.

this is my Work Model:

public function GeoEntities()
{
    return $this->hasMany(\App\GeoEntity::class);
}

public function geoLand()
{
    $builder = $this->GeoEntities()->where("entity_type", 0);
    $relation = new HasOne($builder->getQuery(), $this, 'work_id', 'id');
    return $relation;
}

public function geoLandPoints()
{
    return $this->geoLand->geoPoints();
}

this return $this->intermediateModel->FinalModel(); would work, if intermediate relation is belongsTo() and returns a relation instance.

but in this case, when geoLand is Empty it produce error:

Call to a member function geoPoints() on null

like below line:

$points = $work->geoLandPoints;
  • The Intermediate Relation is a hasMany

i want to have this like relation call geoLandPoints and not geoLandPoints() but,

when intermidate models are null, i want an empty relation.

but i can not figure it out, how to achieve this.

with Fico7489\Laravel\EloquentJoin\Traits\EloquentJoin

using Fico7489\Laravel\EloquentJoin\Traits\EloquentJoin package, i have tried to refactor relation like below:

public function geoLandPoints()
{
    $builder = $this
        ->select("works.*")
        ->join("geo_entities", "works.id", "geo_entities.work_id")
        ->join("geo_points", "geo_entities.id", "geo_points.geo_entity_id")
        ->where("entity_type", 0)
        ->where("works.id", $this->id);
    return new HasMany($builder->getQuery(), $this, "work_id", "id");
}

but it couldn't convert Database Query Builder to Eloquent Query Builder.

Argument 1 passed to Illuminate\Database\Eloquent\Relations\HasOneOrMany::__construct() must be an instance of Illuminate\Database\Eloquent\Builder, instance of Illuminate\Database\Query\Builder given

1

1 Answers

1
votes

Why don't you use the hasOne() method instead of trying to return your own HasOne class? Also, you can use withDefault() so the relationship returns an empty GeoEntity instead of null.

public function geoLand()
{
    return $this->hasOne(\App\GeoEntity::class)->where("entity_type", 0)->withDefault();
}

You could even pass an array of default values. withDefault(['column' => 'value', 'column2' => 'value2', ...])