Laravel 加载关系 - 框架错误?

Laravel loading relations - framework bug?

我遇到了一些奇怪的事情,我认为这可能是框架本身的错误,所以我想知道是否有类似的经历。

我有两个实体:ContactMedia 处于 1:M 关系中。关系定义为:

public function media()
{
    return $this->hasMany(Media::class);
}

现在我看到的问题是,当我继续 show 控制器方法并像这样加载关系时:

public function show(Contact $contact)
{
    $contact->load('media');
    return response()->json($contact);
}

联系人已解决,媒体关系如下:

"first_name": "Melisa",
...
"media": [
    {
        "id": 50,
    ...

但是,如果我修改关系的大小写以便调用:

public function show(Contact $contact)
{
    $contact->load('mEdIa');
    return response()->json($contact);
}

它returns:

"first_name": "Melisa",
...
"m_ed_ia": [
    {
        "id": 50,
    ...

...这真是令人不安。它应该发生吗?

Laravel有这样的行为。要获得相同的密钥 'mEdIa' - 您必须添加到 media 模型。

public static $snakeAttributes = false;

这种行为应该在Laravel的文档中注明,事实并非如此。如果我是你,我会打开一个 issue 来更新关于此行为的文档,看看会有什么反应。

但总而言之,这是一个功能,而不是错误

PHP 的天性在很多方面既敏感又不敏感。对于 类 和方法; PHP 不敏感。

class Contact {
    public function media() {
        return .. relationship;
    }
}

// valid
new CONTACT();
(new contact())->mediA();
// valid reflection
$r = \ReflectionClass('contact');
$r->hasMethod('mediA'); // true

所以这些古怪的东西都是有效的。现在到你说的那个点:

.. from my perspective mEdia shouldn't be allowed. My relationship function name is media, and I want it to be used as such.

那你就得这么写。你因为Laravel依赖于它。

  • PHP根本无法validate/verify.
  • Laravel 必须改变编程语言的性质,其敏感性是通过选择有意设计的。
  • 这里的期望是;你(作为程序员)应该知道 PHP 的敏感性,所以在这种情况下,绝对没有必要验证给定的输入。
  • validate/verify 这样的事情的开销将是巨大的并且没有意义。
$class = 'contact';
$method = 'mediA';

$r = new \ReflectionClass($class);
if($class !== $r->getName()) {
    throw new \Exception('unknown class');
}
if(!in_array($method, array_map(function($method) {
    return $method->name;
}, $methods))) {
    throw new \Exception('unknown method');
}

// valid from here

从各方面来看,$contacts->with('mediA')的用法是完全有效的。

事实上 mediA 在转换为数组时使用 Str::snake('mediA') 变为 medi_a(如此),这只是您必须处理的 Laravel 的一个特性.