0
votes

I have a Model Text which has a 1-to-many-relation called pretext(), returning a 1-to-many-Relationshop to Text, like so:

class Text extends Model
{
    public function pretext(){
       return $this->belongsTo('App\Models\Text', 'pretext_id');
    }

   public function derivates(){
      return $this->hasMany('App\Models\Text', 'pretext_id');
   }
}

If a $text does not have any pretext (which, in my scenario, means $text['pretext_id'] == 0) $text->pretext() shall return the $text itself. When I try

public function pretext(){
   if ( $this->belongsTo('App\Models\Text', 'pretext_id') ) {
       return $this->belongsTo('App\Models\Text', 'pretext_id');
   }
   else {
       return $this;
   }
}

I get the error

local.ERROR: LogicException: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

when the else-part is executed. So my questions are:

  1. How do I turn $this into an object of type Relation? or alternatively:
  2. How can I achieve my goal on a different way?
2
You can't make $this into a Relation. I suggest you check everytime if the Text has a Pretext or not : $text->pretext ? "Has pretext" : "No pretext";.Treast
Just write your relation function without the if/else, then make a separate function that returns either the relation, or itself. Laravel functionality depends on a relation function returning a relation, so you should just wrap the function separately with your custom logic.Jeff
@Jeff Maybe an accessor is a solution, dunno if it works with relations : laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutatorsTreast

2 Answers

1
votes

Try dynamic props

class Text extends Model
{
    protected $appends = ['content'];
    public function pretext(){
       return $this->belongsTo('App\Models\Text', 'pretext_id');
    }

   public function getContentAttribute(){
      $pretext = $this->pretext()->get();
      if ($pretext->count()) {
        return $pretext;
      }
     return $this;
   }
}

Then in controller or view if you have the instance (consider optimizing it if you have N+1 issues)

$obj = Text::find(1);
dd($obj->content);
0
votes

I think you can create another method that calling pretext() and check the returned value.

public function getPretext() {
    $value = pretext();
    return ($value)? $value : $this; 
}