如何最好地链接到Laravel中的多态关系

时间:2016-06-11 22:04:37

标签: php laravel laravel-5.2 laravel-routing

模型 var array = [1,2,3,4]; function productOfArrayExceptSelf(array){ var result = 0; var resultArray = []; var indexes; for(var i = 0; i < array.length; i++){ for(var j = 0; j < array.length; j++){ indexes = array[j]; if(indexes === array[j]){ continue; } } } return result; } 与模型AXY具有多态关系。 Z中的相关字段为:

A(整数外键)
poly_id(字符串poly_typeApp\XApp\Y

给定模型App\Z的实例,我可以成功使用A来检索X,Y或Z类型的相关对象。(例如$a->poly)。

{"id":1,"name":Object X}的Blade模板中,如何生成A的显示链接,例如'/ x / 1'?我想到的是X,但据我所知,我们实际上并没有路径的“x”部分 - 只有poly_id,poly_type和两个对象。

我错过了什么吗?一个解决方案,比如获取poly_type字符串'App \ X'并将最后一段和小写分开以获得'x',但这看起来并不理想,并且可能定义的路线可能是其他的。

顺便说一句,在Rails中,我很确定你可以做URL::route('x.show', $a-poly_>id),它会神奇地返回URL'/ x / 3'。不确定Laravel是否可以做到这一点。我尝试了link_to($a->poly)但它不起作用。

5 个答案:

答案 0 :(得分:4)

使用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::get('/a/show/{a}/{poly}', 'AController@index');

和控制器:

class AController extends Controller {

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

所以/ a / show / 1 / xs是有效路径

答案 1 :(得分:0)

我认为我的解决方案如下。在多态关系的多端上的所有表都将具有标识routeaction的属性(取决于我对这个想法的看法)。

型号:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Y extends Model
{
    /**
     * The route name associated with the model.
     *
     * @var string
     */
    protected $routeName= 'path.to.y.show';
}

然后,您可以使用类似这样的代码来查找路线,而不必考虑最后的型号:

route($a->poly->routeName, $a->poly)

或者,对于hasMany

@foreach($a->polys as $object) 
    <a href="{{route($object->routeName, [$object])}}">But what name?</a>
@endforeach

不过,我不知道这是否可以接受。如果您尚未在模型上定义routeName,则会遇到错误。 我也不确定模型是否应该了解路由!

为了确定要显示的名称,是否应该定义某种getGenericNameAttribute来从模型中返回适当的属性?


我正在回答,希望有人有一个更优雅的解决方案。例如,注册一个服务提供商,然后:

  • 允许定义到模型映射的路径(有点像策略?);和
  • 根据传递的模型/模型类确定正确的路线。

只是我不知道该怎么做!

答案 2 :(得分:0)

这似乎过于简单,但您可以使用类似的方法来解决问题

我会创建一个类似这样的控制器:

use App\Http\Controllers\Controller;
use A;
use X;
use Y;
use Z;    

class PolyController extends Controller {

public function aPoly(A $a)
{
    $poly = $a->ploy;
    switch ($ploy)
        case instance of X:
            return response()->redirectToRoute('X route name', $poly);
            break;
        case instance of Y:
            return response()->redirectToRoute('Y route name', $poly);
            break;
       case instance of Z:
            return response()->redirectToRoute('Y route name', $poly);
            break;
       default:
            report(new Exception('Failed to get route for ploy relationship');
   }
}

这将允许您在路由文件中使用以下内容:

Route::get('enter desired url/{a}', 'PolyController@aPoly')->name('name for poly route');

然后在您的控制器中执行以下操作:

<a href="{{ route('name for poly route', $a) }}">$a->ploy->name</a>

这就是我要处理的情况

答案 3 :(得分:0)

Laravel目前没有Rails那样的简单解决方案。这是因为路由名称和模型名称之间没有隐式连接。有一个 convention 命名,但是它并没有真正应用到代码中。我无法索取模型的URL,我需要致电route('model.show', $model)

这里的其他一些解决方案建议使用重定向控制器,但这种方法不方便且用户体验(以及SEO)差。最好创建一个可以生成所需路线的辅助功能-这样,该功能就可以在应用程序中的任何位置使用,并且与模型或控制器层无关。

如果您想控制访问的实际页面(即不仅仅是显示路线),则可以包装route帮助程序,该帮助程序可以采取所需的操作并生成正确的URL。

use Illuminate\Database\Eloquent\Model;

function poly_route(string $route, Model $model): string
{
    return route($model->getTable() . '.' . $route, $model);
}

这将使您执行类似poly_route('show', $poly)的操作;

通常,您将在bootstrap/helpers.php中放置帮助程序功能,并将该文件注册到composer.json文件中-如果您已经在使用帮助程序文件。当然,如果您不使用帮助程序文件,那么此解决方案可能已经很骇人。

然后我建议您探索将函数移至模型上的方法。

class Poly extends Model
{
    public function route($name)
    {
        return route($this->getTable() . '.' . $route, $this);
    }
}

然后,您可以简单地致电$poly->route('show')。同样,这两种解决方案都不是完全“优雅”的,但是在应用程序中支持各种用例的情况下,可能会遇到大量的if / else或switch情况。希望Laravel可以为以后的事情提供更好的功能。

答案 4 :(得分:0)

使用Laravel不可能绑定路线和模型。但是我对你的问题有个主意。

您可以将mutators的自定义属性添加到A模型中,该属性将负责确定调用对象时使用的路由。例如;

A模型;

/**
 * Get the route
 *
 * @return string
 */
public function getRouteAttribute()
{
    $route = null;
    switch ($this->poly_type){
        case 'App\X':
            $route = 'your_x_route_name';
            break;
        case 'App\Y':
            $route = 'your_y_route_name';
            break;
        case 'App\Z':
            $route = 'your_z_route_name';
            break;
    }
    return $route;
}

我们可以认为它就像是Factory方法。

当我们想要使用它时,我们可以使用一条路线。

@foreach($a->polys as $object) 
    <a href="{{ route($a->route, [your parameters.]) }}">But what name?</a>
@endforeach

这可能不是完美的做法,但我认为从一个角度进行管理很有用。