【问题标题】:What model will be returned when using relationship from extended model?使用扩展模型中的关系时将返回什么模型?
【发布时间】:2020-03-04 21:41:14
【问题描述】:

考虑以下场景:
两个模型从一个包中扩展而来,这些模型之间的关系在包中定义。
例如,医生和患者:

应用中的医生:

namespace App;

use SomePackage\Doctor as VendorDoctor

class Doctor extends VendorDoctor
{
    (...)
}

应用程序中的患者:

namespace App;

use SomePackage\Patient as VendorPatient

class Patient extends VendorPatient
{
    (...)
}

供应商包中的医生:

namespace SomePackage;

class Doctor extends Model
{
    public function patients()
    {
        return $this->hasMany(Patient::class);
    }
}

供应商包裹中的患者:

namespace SomePackage;

class Patient extends Model
{
    public function doctor()
    {
        return $this->belongsTo(Doctor::class);
    }
}

使用关系时会返回哪个模型?
示例:

$patient = \App\Patient::find($id);
$doctor = $patient->doctor;

$doctor 将是具有该模型可用功能的 App\Doctor,还是 SomePackage\Doctor?

【问题讨论】:

    标签: php laravel eloquent


    【解决方案1】:

    默认为SomePackage\Doctor。不过,您可以覆盖这种关系。

    【讨论】:

    • 就像我当时担心的那样。我们有几个项目连接到同一个数据库(一个 API、一个管理面板……),所以我们选择了一个包含模型的自定义包,以便在项目之间共享。但是,如果无论如何都必须覆盖这些关系,那就有点超出了拥有包的主要目的。
    【解决方案2】:

    默认情况下它将返回SomePackage\Doctor,因为SomePackage中的代码:

    public function patients()
        {
            return $this->hasMany(Patient::class);
        }
    

    这里的Patient::class 是一个特殊的常量,它包含到 Patient 类的完整路径(带有命名空间)。它包含类似SomePackage\Patient 的内容,该路径属于包本身。所以,你不能只通过使用另一个同名的类来改变它。

    但您可以在 App\Doctor 类中使用 redefine 整个方法。

    namespace App;
    
    use SomePackage\Doctor as VendorDoctor
    
    class Doctor extends VendorDoctor
    {
        public function patients()
        {
            return $this->hasMany(\App\Patient::class);
        }
    }
    

    之后App\Doctor 将返回与App\Patient 的关系。

    $doctor = \App\Doctor::find($id);
    $patient = $doctor->patient;
    //$patient containt Collection of App\Patient models
    

    其实你甚至不需要定义完整的\App\Patient:class 路径,因为这里你已经在App 命名空间中,我只是添加它以便更好地理解。

    【讨论】:

    • 就像我当时担心的那样。我们有几个项目连接到同一个数据库(一个 API、一个管理面板……),所以我们选择了一个包含模型的自定义包,以便在项目之间共享。但是,如果无论如何都必须覆盖这些关系,那有点超出了拥有该软件包的主要目的。
    • 并非如此。除了使用return $this->hasMany(Patient::class);,您还可以从方法或常量获取Patient::class 的路径。喜欢self::getPatientPath()self::patientClass。因此,当您扩展 Model 时,您只需覆盖一个属性。
    • 您甚至可以通过获取正确的命名空间来动态地解决您的任务。查看更多stackoverflow.com/questions/2317343/…
    • @MrEvers 这个答案对你来说够用还是还有别的?
    • 这是我一定要更详细地研究的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 2015-04-18
    • 2017-01-01
    • 2018-08-10
    • 1970-01-01
    • 2015-01-31
    相关资源
    最近更新 更多