Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Best to Link to a Polymorphic Relation in Laravel

Model A has a polymorphic relation to models X, Y, Z. Relevant fields in A are:

poly_id (integer foreign key)
poly_type (string App\X, App\Y or App\Z)

Given an instance of model A, I can successfully use $a->poly to retrieve the related object of type X, Y or Z. (E.g. {"id":1,"name":Object X}).

In a Blade template for A, how should I generate an show link to X such as '/x/1'? What springs to mind is URL::route('x.show', $a-poly_>id) however as far as I can see, we don't actually have the 'x' part of the route available to us - only the poly_id, poly_type and both objects.

Am I missing something? A solution like taking the poly_type string 'App\X' and split off the last segment and lowercase to get 'x' but that doesn't seem ideal, and potentially the defined route could be something else.

As an aside, in Rails I'm pretty sure you can do link_to($a->poly) and it would magically return the URL '/x/3'. Not sure if Laravel can do that. I tried url($a->poly) and it doesn't work.

like image 944
Ben Avatar asked Jun 11 '16 22:06

Ben


1 Answers

Use MorphToMany & MorphedByMany

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class A extends Model
{
    public function xs()
    {
        return $this->morphedByMany('App\X', 'poly_type');
    }

    public function ys()
    {
        return $this->morphedByMany('App\Y', 'poly_type');
    }

    public function zs()
    {
        return $this->morphedByMany('App\Z', 'poly_type');
    }

 }

Route:

Route::get('/a/show/{a}/{poly}', 'AController@index');

And Controller:

class AController extends Controller {

    public function index(A $a, $poly)
    {
         dd($a->{$poly}->first()); // a $poly Object
    }
}

So, /a/show/1/xs is a valid path

like image 81
Murat Tutumlu Avatar answered Oct 11 '22 05:10

Murat Tutumlu