Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eloquent relations - attach (but don't save) to Has Many

I have the following relations set up:

class Page {
    public function comments() {
        return $this->hasMany('Comment');
    }
}

class Comment {
    public function page() {
        return $this->belongsTo('Page');
    }
}

Pretty bog standard. One page can have many comments, and one comment belongs to a single page.

I'd like to be able to create a new page:

$page = new Page;

and a comment

$comment = new Comment;

and attach the comment to the page, without saving any of it

$page->comments->associate($comment);

I've tried the following:

// These are for one-to-many from the MANY side (eg. $comment->page->associate...)
$page->comments->associate($comment);   // Call to undefined method Illuminate\Database\Eloquent\Collection::associate()
$page->comments()->associate($comment); // Call to undefined method Illuminate\Database\Query\Builder::associate()

// These 2 are for many-to-many relations, so don't work
$page->comments->attach($comment);      // Call to undefined method Illuminate\Database\Eloquent\Collection::attach()
$page->comments()->attach($comment);    // Call to undefined method Illuminate\Database\Query\Builder::attach()

// These 2 will (if successful) save to the DB, which I don't want
$page->comments->save($comment);        // Call to undefined method Illuminate\Database\Eloquent\Collection::save()
$page->comments()->save($comment);      // Integrity constraint violation: 1048 Column 'page_id' cannot be null

The really odd thing is that doing the opposite (attaching the page to the comment) works correctly:

$comment->page()->associate($page);

The relevant docs are here but they don't make any mention of attaching to the ONE side of a one-to-many. Is it even possible? (I feel like it should be)

like image 794
Joe Avatar asked May 30 '14 09:05

Joe


People also ask

What is belongsTo in Laravel?

BelongsTo relationship in laravel is used to create the relation between two tables. belongsTo means create the relation one to one in inverse direction or its opposite of hasOne. For example if a user has a profile and we wanted to get profile with the user details then we can use belongsTo relationship.


3 Answers

It sounds like you just want to add the new comment object to the page's comments collection - you can do that easily, using the basic colection add method:

$page = new Page; $comment = new Comment; $page->comments->add($comment); 
like image 102
Benubird Avatar answered Sep 21 '22 15:09

Benubird


You can't do since there are no ids to link.

So first you need to save the parent ($page) then save the child model:

// $page is existing model, $comment don't need to be $page->comments()->save($comment); // saves the comment 

or the other way around, this time without saving:

// again $page exists, $comment don't need to $comment->page()->associate($page); // doesn't save the comment yet $comment->save(); 
like image 23
Jarek Tkaczyk Avatar answered Sep 23 '22 15:09

Jarek Tkaczyk


according to Benubird I just wanted to add something as I stumbled over this today:

You can call the add method on a collection like Benubird stated. To consider the concerns of edpaaz (additional fired query) I did this:

$collection = $page->comments()->getEager(); // Will return the eager collection
$collection->add($comment) // Add comment to collection

As far as I can see this will prevent the additional query as we only use the relation-object.

In my case, one of the entities were persistent while the first (in your case page) was not (and to be created). As I had to process a few things and wanted to handle this in a object manner, I wanted to add a persistent entity object to a non persistent. Should work with both non persistent, too though.

Thank you Benubird for pointing me to the right direction. Hope my addition helps someone as it did for me.

Please have in mind that this is my first stackoverflow post, so please leave your feedback with a bit concern.

like image 41
Julius Blatt Avatar answered Sep 25 '22 15:09

Julius Blatt