简体   繁体   English

无法渴望在Laravel中加载一对一关系

[英]Can't eager-load a One-to-One relation in Laravel

In Laravel 5.2 I'm trying to eager load a User along with its Usersettings with this piece of code: App\\User::with('usersettings')->get() , but it fails, and I can't seem to figure out why. 在Laravel 5.2中,我试图通过以下代码渴望加载一个User及其Usersettings: App\\User::with('usersettings')->get() ,但是它失败了,我似乎无法找出原因。 This is the given error. 这是给定的错误。

BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::usersettings()'

I've read the laravel docs and I've watched a lot of Laracasts , and this worked before, so I get the idea I'm missing something really small and probably obvious. 我已经阅读了laravel文档,并且看了很多Laracasts ,并且以前也能用 ,所以我觉得我缺少了一些很小的东西,也许很明显。

User.php User.php

<?php

namespace App;

/* User with fields: id, email */
class User extends Illuminate\Database\Eloquent\Model {
    protected $table = 'users';

    public function usersettings() {
        return $this->hasOne("App\Usersettings", "userid");
    }
}

Usersettings.php Usersettings.php

<?php

namespace App;

/* Settings with fields: id, userid, textcolor */
class Usersettings extends Illuminate\Database\Eloquent\Model {
    protected $table = 'usersettings';

    public function user() {
        return $this->belongsTo('App\User', 'userid');
    }
}

//Edit: I already tried lowercasing the s. //编辑:我已经尝试过将s小写。 This typo might have snuck in copying it to SO, but the error was there, and still is there, even after fixing it. 这种错别字可能是偷偷将其复制到SO,但是即使在修复它之后,错误仍然存​​在,并且仍然存在。

//Edit: //编辑:

<?php

namespace App;

use App\UserSettings;

class User extends Illuminate\Database\Eloquent\Model {
    protected $table = 'users';

    public function settings() {
        return $this->hasOne(UserSettings::class, "userid");
    }
}

If I run php artisan tinker >>> App\\User::with('settings')->get() , it works as expected, but below 如果我运行php artisan tinker >>> App\\User::with('settings')->get() ,它可以按预期工作,但是在下面

<?php

namespace App;

use App\UserSettings;

class User extends Illuminate\Database\Eloquent\Model {
    protected $table = 'users';

    public function usersettings() {
        return $this->hasOne(UserSettings::class, "userid");
    }
}

gives BadMethodCallException with message 'Call to undefined method Illuminate\\Database\\Query\\Builder::usersettings()' when I run php artisan tinker >>> App\\User::with('usersettings')->get() . 当我运行php artisan tinker >>> App\\User::with('usersettings')->get()时,给出BadMethodCallException with message 'Call to undefined method Illuminate\\Database\\Query\\Builder::usersettings()' Likewise when I rename the method to abc and run php artisan tinker >>> App\\User::with('abc')->get() (that fails as well) 同样,当我将方法重命名为abc并运行php artisan tinker >>> App\\User::with('abc')->get() (同样失败)

You mistyped when defining the relation on the User model: 在用户模型上定义关系时输入错误:

public function usersettings() {
    return $this->hasOne("App\Usersettings", "userid");
}

I would suggest some cleanup: name the tables 'users' and 'user_settings', rename the field 'userid' to 'user_id', rename the 'Usersettings' model to 'UserSettings'. 我建议进行一些清理:将表命名为“ users”和“ user_settings”,将“ userid”字段重命名为“ user_id”,将“ Usersettings”模型重命名为“ UserSettings”。

That way you dont need to explicitly define table names and foreign keys, because you follow the conventions and Laravel can "guess" those. 这样,您就无需显式定义表名和外键,因为您遵循约定,Laravel可以“猜测”它们。

You can also rename the the relation 'usersettings()' to 'settings()', since its obvious that they're the users' settings. 您也可以将关系“ usersettings()”重命名为“ settings()”,因为很明显它们是用户的设置。 Then you can fetch it like: 'User::with('settings')->get()'. 然后,您可以像这样获取它:'User :: with('settings')-> get()'。

Did you try running composer dump-autoload after you changed your model relationships? 更改模型关系后,是否尝试运行composer dump-autoload

Just to make sure you're aware of this: you don't actually need to define the relationship in your UserSettings model to achieve what you want, only define the relationship in the User model. 只是要确保您了解这一点: 实际上,您不需要在UserSettings模型中定义关系即可实现所需的功能,只需在User模型中定义关系即可。 This is because you'd only need to get the settings in the context of the User, not the other way around. 这是因为您只需要在用户的上下文中获取设置,而不需要相反的方式。

Code for the User model: 用户模型的代码:

<?php

namespace App;

use App\UserSettings;

class User extends Illuminate\Database\Eloquent\Model {

    public function userSettings() {
        return $this->hasOne(UserSettings::class);
    }
}

UserSettings model: make sure it's camel case and that userid is present in your migration (the convention in your case would be to have user_id , so I would rename that column in your migration because then Eloquent will pick it up automatically and you don't need the second parameter in your User model's hasOne() definition). UserSettings模型:确保它是驼峰式的,并且迁移中存在userid (在这种情况下,约定是user_id ,所以我将在迁移中重命名该列,因为Eloquent会自动将其选中,而您不会需要在用户模型的hasOne()定义中使用第二个参数)。 Also, rename your table to user_settings if you can. 另外,如果可以,将表重命名为user_settings That's another Eloquent convention, this one being that the model name UserSettings translates the camel case S letter in the middle of the classname to _ (and as a matter of fact, you shouldn't even need to explicitly state the table name if you've used the name user_settings ). 这是另一种口才的惯例,那就是模型名称UserSettings将类名中间的驼峰大小写字母S转换为_ (事实上​​,如果您需要将表名声明为我们使用了user_settings名称)。

Code for the UserSettings model: UserSettings模型的代码:

<?php

namespace App;

/* Settings with fields: id, userid, textcolor */
class UserSettings extends Illuminate\Database\Eloquent\Model {
    protected $table = 'user_settings';
}

Now, you should be able to do the below action. 现在,您应该可以执行以下操作。 Note that the with parameter needs to be the relation function name from the User model. 请注意, with参数必须是User模型中的关系函数名称。

$usersThatHaveSettingsIncludedInTheResults = User::with('userSettings')->get();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM