Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eloquent: Use another column as primary key on a relationship

I have a table Books: with an ID (int) and a ISBN (string) the ISBN is a unique key. I have another table where I store the isbn for the book. On the book model I have: $this->hasMany('Other', 'isbn', 'isbn');

But that ignores the isbn. Do you know any way of doing this?

Temporary fix:

$this->primaryKey = 'isbn';
return $this->hasMany('Other', 'isbn');
like image 698
Marco Rivadeneyra Avatar asked May 14 '13 19:05

Marco Rivadeneyra


3 Answers

Since at least 4.2, you can now specify the local key in the hasMany.

From the documentation (4.2, 5.2, 5.4, 5.7) :

return $this->hasMany('Comment', 'foreign_key', 'local_key');
like image 70
Maxime Morin Avatar answered Dec 09 '22 11:12

Maxime Morin


Stumbled into the same problem lately, I'm not yet sure whether this would work, but as an idea:

class Book {
    public function isbn() {
        // instead of hasMany
        return ISBN::where('isbn', $this->isbn);
    }
}
like image 42
Slava V Avatar answered Dec 09 '22 09:12

Slava V


This is not possible - there are only a few instances where you would want to link to a unique column on a table that is not also the pk. That said, other frameworks have developed methods of changing the primary key, and no one has formally requested it for Laravel yet. You can write up a proposal on GitHub and it might make it in to a future release.


Looking at your specific example for a moment - this may have unexpected outcomes when you come to use the relationship in eager loading situations, and it only accounts for one side of the relationship. When you add belongsTo on Other you'll have the reverse problem.

It may be possible to setup a relationship through isbn; however this would take the form of Book hasOne ISBN, ISBN belongsTo Book, ISBN hasMany Others, Other belongsTo ISBN; and accessing properties would look like $book->isbn->others or $other->isbn->book.

My last suggestion would be to extend Book, and set the new class' primary key as isbn and base all your relationships on that model. It's not ideal, but it would be less painful that some other solutions.

like image 35
Phill Sparks Avatar answered Dec 09 '22 11:12

Phill Sparks