Leon's avatar
Level 2

How to remove item from relationship collection

L5.2

I have a model with a hasMany relationship like this

public function lines()
{
    return $this->hasMany('TransactionLine', 'transactionid', 'id');
}

I have loaded the relationship and want to remove an item from the collection, I can do that with something like

$this->lines = $this->lines->filter ( ... );

That works OK, however if I save the model after doing that

$this->save()

it tries to include -lines- in the database query and I get a SQL error -

QueryException in Connection.php line 713:PDOException in Connection.php line 462: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'lines' in 'field list'

I guess it's seeing -lines- as a property now rather than a method/relationship so tries to include it in the DB query?

I need to know how to remove an item from the collection returned by the relationship, in such a way that I can still save the model.

Any help is much appreciated. Thanks :)

0 likes
8 replies
InaniELHoussain's avatar

share with us your code to understand what you want to do and provid an alternative

Leon's avatar
Level 2

Code is there already?

hasMany relationship on a model $model->lines = function () { ... }

Remove an item from the collection $model->lines = $model->lines->filter( ... )

Save the model $model->save()

Get a SQL error - Unknown column 'lines' in 'field list'

Thanks :)

Hesto's avatar

You absolutely can't do this:

$model->lines = $model->lines->filter( ... );

What do you mean by "Remove from collection"? You want to delete records from DB or you want to associate them with another parent model? If you defined foreign key for lines i think it can't be empty.

Leon's avatar
Level 2

No, it would appear not! :)

I want to delete them from my database, which is fine, I can do $lines->find($id)->delete() - that takes care of the database, but the line is still in the collection that's returned from $model->lines.

After deleting the line from the database I use the model for other things later on, so I want to remove the line from the collection (ie what comes back from $model->lines ) too. If the line is deleted in the database, but still present in the collection the the model has it gets confusing and messy.

I guess I could re-load the lines $model->load('lines') - but seems really counter-intuitive - why go back to the database and load the lines when I have them already and know which one needs removing.

Hesto's avatar

In my opinion the load method is best you can do. Laravel is all about KISS. If you don't have realy good argument to complicate smth (like your lines relationship has thousends of records), just don't.

Snapey's avatar

You could remove the relation entirely before save?

something like unset $this->lines and $this->save()

Leon's avatar
Level 2

I managed to get round this by telling the model to ignore the lines attribute like this :

public function getDirty()
{
    $dirty = parent::getDirty();
    unset($dirty['lines']);
    return $dirty;
}  

Seems a bit hackey, but works - would love to see a better solution if someone has one.

mane_olawale's avatar

You don't need to do it hackey. You can now do this:


     $model->setRelation('lines', null);

This will remove the relationship from the $relations property of the model and you can use it to add relationships to models without running query.

This gives you an advantage over "Maximum stack depth" error and circular relationships.

1 like

Please or to participate in this conversation.