Laravel:返回多态关系的命名空间所有者 [英] Laravel: Returning the namespaced owner of a polymorphic relation

查看:115
本文介绍了Laravel:返回多态关系的命名空间所有者的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以找到一些关于这个但没有明确的解决方案的讨论。这里有两个链接,虽然我将在这里介绍我自己的问题。



Github问题



Laravel.io讨论



简单说明



/ p>

当使用$ morphClass时,$ morphClass的内容被保存在当尝试查找多态关系的所有者时,数据库作为变体类型用于类名。这导致一个错误,因为$ morphClass的整点是它不是类的完全命名空间的名称。



如何定义多态关系的类名应该使用?



更多详细说明



这是一个更详细的解释,解释我正在试图做和为什么我试图用例子来做。



当在Laravel中使用多态关系时,数据库中保存的morph_type类型被假定为该类。



所以在这个例子中:

  class Photo extends雄辩{

public function imageable()
{
return $ this-> morphTo();
}

}

class工作人员扩展Eloquent {

公共功能照片()
{
返回$ this-> morphOne('Photo','imageable');
}

}

类订单扩展Eloquent {

公共功能照片()
{
返回$ this-> morphOne('Photo','imageable');
}

}

数据库将如下所示:

  staff 

- id - integer
- 名称 - 字符串

订单

- id - 整数
- 价格 - 整数

照片

- id - 整数
- 路径 - 字符串
- imageable_id - 整数
- imageable_type - string

现在第一行照片可能如下所示:


id,path,imageable_id,imageable_type



1,image.png,1,Staff


现在我可以从员工模型或员工访问照片从照片模型。

  //查找工作人员并转储他们的照片
$ staff = Staff :: find (1);

var_dump($ staff->照片);

//查找照片并转储相关员工
$ photo = Photo :: find(1);

var_dump($ photo-> imageable);

到目前为止这么好。但是当我命名空间时,我遇到一个问题。

 命名空间应用程序/存储; 
class Order {}

命名空间App / Users;
class Staff {}

命名空间App / Photos;
class Photo {}

现在我的数据库中保存的是这样的:


id,path,imageable_id,imageable_type



1,image.png,1,App /用户/员工


但是我不想要。在数据库中保存完整的名称空间的类名称是一个糟糕的想法!



幸运的是,Laravel有一个选项可以设置一个$ morphClass变量。像这样:

  class Staff Enloquent {

protected $ morphClass ='staff';

public function photos()
{
return $ this-> morphOne('Photo','imageable');
}

}

现在我的数据库中的行将看起来像这样,这是真棒!


id,path,imageable_id,imageable_type



1,image.png,1,员工


获取工作人员的照片工作绝对正常。

  //查找工作人员并转储他们的照片
$ staff = Staff :: find(1);

//这个工程!
var_dump($ staff->照片);

然而,查找照片所有者的多态魔法不起作用:

  //查找照片并转储相关员工
$ photo = Photo :: find(1);

//这不行!
var_dump($ photo-> imageable);

//错误:没有找到类'staff'

作为使用$ morphClass时使用什么类名的多态关系的一种方式,但是我不能在文档,源代码中或通过Google找到任何关于这个应用程序的引用。



任何帮助?

解决方案

有两个简单的方法 - 一个在下面,另一个在@ lukasgeiter的答案中提出由Taylor Otwell,我绝对建议检查:

  // app / config / app.php或任何你喜欢的
'aliases'=> [
...
'MorphOrder'=> 'Some\Namespace\Order',
'MorphStaff'=> 'Maybe\Another\Namespace\Staff',
...
]

//员工模型
protected $ morphClass ='MorphStaff';

//订单模型
protected $ morphClass ='MorphOrder';

完成

  $ photo = Photo :: find(5); 
$ photo-> imageable_type; // MorphOrder
$ photo-> imageable; // Some\Namespace\Order

$ anotherPhoto = Photo :: find(10);
$ anotherPhoto-> imageable_type; // MorphStaff
$ anotherPhoto-> imageable; // Maybe\Another\Namespace\Staff

我不会使用真正的类名订单 Staff )以避免可能的重复。有一些东西被称为 MorphXxxx 的机会很少,所以它很安全。



这比更好存储命名空间(我不介意数据库中的外观,但是如果您更改某些内容,将会变得不方便 - 而不是 App \Models\User 使用 Cartalyst\Sentinel\User 等),因为所有你需要的是通过别名配置交换实现



但是也有缺点 - 你不会知道,模型是什么,只需检查db,以防万一它对你很重要。


I can find a number of discussions regarding this but no clear solution. Here are two links, although I will cover everything in my own question here.

Github Issues

Laravel.io discussion

Simple Explanation

This is a simple explanation of my problem for anyone already familiar with Laravel's polymorphic relationships.

When using $morphClass, the contents of $morphClass which is saved in the database as the morph "type" is used for the classname when trying to find the owner of a polymorphic relation. This results in an error since the whole point of $morphClass is that it is not a fully namespaced name of the class.

How do you define the classname that the polymorphic relationship should use?

More Detailed Explanation

This is a more detailed explanation explaining exactly what i'm trying to do and why i'm trying to do it with examples.

When using Polymorphic relationships in Laravel whatever is saved as the "morph_type" type in the database is assumed to be the class.

So in this example:

class Photo extends Eloquent {

    public function imageable()
    {
        return $this->morphTo();
    }

}

class Staff extends Eloquent {

    public function photos()
    {
        return $this->morphOne('Photo', 'imageable');
    }

}

class Order extends Eloquent {

    public function photos()
    {
        return $this->morphOne('Photo', 'imageable');
    }

}

The database would look like this:

staff

 - id - integer
 - name - string

orders

 - id - integer
 - price - integer

photos

 - id - integer
 - path - string
 - imageable_id - integer
 - imageable_type - string

Now the first row of photos might look like this:

id,path,imageable_id,imageable_type

1,image.png,1,Staff

Now I can either access the Photo from a Staff model or a Staff member from a Photo model.

//Find a staff member and dump their photos
$staff = Staff::find(1);

var_dump($staff->photos);

//Find a photo and dump the related staff member
$photo = Photo::find(1);

var_dump($photo->imageable);

So far so good. However when I namespace them I run into a problem.

namespace App/Store;
class Order {}

namespace App/Users;
class Staff {}

namespace App/Photos;
class Photo {}

Now what's saved in my database is this:

id,path,imageable_id,imageable_type

1,image.png,1,App/Users/Staff

But I don't want that. That's a terrible idea to have full namespaced class names saved in the database like that!

Fortunately Laravel has an option to set a $morphClass variable. Like so:

class Staff extends Eloquent {

    protected $morphClass = 'staff';

    public function photos()
    {
        return $this->morphOne('Photo', 'imageable');
    }

}

Now the row in my database will look like this, which is awesome!

id,path,imageable_id,imageable_type

1,image.png,1,staff

And getting the photos of a staff member works absolutely fine.

//Find a staff member and dump their photos
$staff = Staff::find(1);

//This works!
var_dump($staff->photos);

However the polymorphic magic of finding the owner of a photo doesn't work:

//Find a photo and dump the related staff member
$photo = Photo::find(1);

//This doesn't work!
var_dump($photo->imageable);

//Error: Class 'staff' not found

Presumably there must be a way to inform the polymorphic relationship of what classname to use when using $morphClass but I cannot find any reference to how this should work in the docs, in the source code or via Google.

Any help?

解决方案

There are 2 easy ways - one below, other one in @lukasgeiter's answer as proposed by Taylor Otwell, which I definitely suggest checking as well:

// app/config/app.php or anywhere you like
'aliases' => [
    ...
    'MorphOrder' => 'Some\Namespace\Order',
    'MorphStaff' => 'Maybe\Another\Namespace\Staff',
    ...
]

// Staff model
protected $morphClass = 'MorphStaff';

// Order model
protected $morphClass = 'MorphOrder';

done:

$photo = Photo::find(5);
$photo->imageable_type; // MorphOrder
$photo->imageable; // Some\Namespace\Order

$anotherPhoto = Photo::find(10);
$anotherPhoto->imageable_type; // MorphStaff
$anotherPhoto->imageable; // Maybe\Another\Namespace\Staff

I wouldn't use real class names (Order and Staff) to avoid possible duplicates. There's very little chance that something would be called MorphXxxx so it's pretty secure.

This is better than storing namespaces (I don't mind the looks in the db, however it would be inconvenient in case you change something - say instead of App\Models\User use Cartalyst\Sentinel\User etc) because all you need is to swap the implementation through aliases config.

However there is also downside - you won't know, what the model is, by just checking the db - in case it matters to you.

这篇关于Laravel:返回多态关系的命名空间所有者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆