Laravel 应用程序从 4.2 升级到 5 时的多态关系

Polymorphic relations in upgraded Laravel app from 4.2 to 5

简短:一些相关模型正确返回实例,但有些不是(多态模型)。

我有这三个模型:

app/Models/User.php

<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function company()
    {
        return $this->hasOne('App\Company');
    }
}

app/Models/Company.php

<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class Company extends Model {

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

    public function address()
    {
        // Also tested with morphMany, without success
        return $this->morphOne('App\Address', 'addressable');
    }

}

app/Models/Address.php

<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class Address extends Model {

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

}

控制器:

app/Http/Controllers/MyController.php

<?php namespace App\Http\Controllers;

// ... many "use" clauses not relevant to the question
use Auth;
// ...

use App\Address;
use App\Company;
use App\User;

class MyController extends Controller {

    // Ok here
    $user = Auth::user();

    // Ok here, too
    $company    = $user->company()->first();

    // Here is the problem; $address is null
    $address    = $company->address()->first();

}

$company->address()->first(); 总是在 Laravel 5 中返回 null$address,但它在 Laravel 4.2

中运行良好

如果您打开数据库 - 您会看到旧 L4 数据中的关系存储为:UserCompany

您需要 运行 一个脚本来将列更新为新的命名空间名称 - 例如 App\UserApp\Company

这是因为您现在正在为您的模型命名空间 - 所以 Laravel 需要知道要调用哪个命名空间。

连同@The Shift Exchange 的回答并按照我的问题示例,您可以关注 this approach:

不是在 address table addressable_type 列值中添加名称空间(这是一个有效的解决方案),您可以使用 $morphClass:

<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class Company extends Model {

    protected $morphClass = 'Company';

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

    public function address()
    {
        // Also tested with morphMany, without success
        return $this->morphOne('App\Address', 'addressable');
    }

在 L4 中模型默认没有命名空间,因此它们在您的 table 中保存为 ModelName,而现在在 L5 中它们更像是 Namespace\ModelName 并且以相同的方式检索.

也就是说,您保存在 L4 中的数据需要调整以匹配您当前的模型,或者您可以在模型上使用 protected $morphClass

但是,对于后一种解决方案,请考虑