【问题标题】:Make a custom model that will get data from another model laravel 5.8制作一个自定义模型,该模型将从另一个模型 laravel 5.8 获​​取数据
【发布时间】:2019-12-31 06:37:12
【问题描述】:

我有一个模型,它是存储各种表的外键数据。这是模型的详细信息:

class InstituteStage extends Model
{
    protected $guarded = [];

    public function branch()
    {
        return $this->belongsTo('App\Model\Branch');
    }

    public function version()
    {
        return $this->belongsTo('App\Model\Version');
    }

    public function shift()
    {
        return $this->belongsTo('App\Model\Shift');
    }

    public function stage()
    {
        return $this->belongsTo('App\Model\Stage');
    }

    public function academic_year()
    {
        return $this->belongsTo('App\Model\AcademicYear');
    }

}

现在,如果我获取数据,我正在获取这些字段:

Array
(
    [0] => Array
        (
            [id] => 3
            [stage_for] => Teachers
            [branch_id] => 1
            [version_id] => 1
            [shift_id] => 1
            [stage_id] => 1
            [academic_year_id] => 1
        )

    [1] => Array
        (
            [id] => 4
            [stage_for] => Students
            [branch_id] => 2
            [version_id] => 2
            [shift_id] => 2
            [stage_id] => 2
            [academic_year_id] => 2
        )
)

现在我想要其他表的详细信息(例如名称)。我正在寻找的回应是:

Array
(
    [0] => Array
        (
            [id] => 3
            [stage_for] => Teachers
            [institute_stage_name] => "branch_name->version_name->shift_name->stage_name" 
        )

    [1] => Array
        (
            [id] => 4
            [stage_for] => Students
            [institute_stage_name] => "branch_name->version_name->shift_name->stage_name" 
        )
)

我可以使用预加载获取数据并将它们连接到前端。但我想使用将返回此详细信息的自定义模型。有没有可能得到这个结构!

我在我的模型中创建了另一个静态方法并获取了所有数据:

public static function student_institute_stage_data()
{
    return static::where([
        ['stage_for', 'Students'],
        ['status', 'active']
    ])
    ->with(['branch', 'version', 'shift', 'stage'])
    ->get();
}

然后在我的控制器中:

$instituteStage = InstituteStage::student_institute_stage_data();

在那之后在我的刀片中,我正在这样做 ->

@foreach ($instituteStage as $stage)
    <option value="{{ $stage->id }}" {{ old('institute_stage_id') === $stage->id ? 'selected' : '' }} >{{ $stage->branch->name . "->" . $stage->version->name . "->" . $stage->shift->name . "->" . $stage->stage->name }}</option>
@endforeach

【问题讨论】:

  • 你能提供你控制器的代码吗,你试过什么?
  • 现在我正在做很长的路要走,使用急切加载分别获取所有数据,然后进入刀片,我将它们连接到我需要的地方。
  • 您需要在控制器中执行此操作,因此如果您共享最少的代码部分,将有助于其他人解决您的问题。 :)

标签: laravel laravel-5 eloquent laravel-5.8


【解决方案1】:

您可以在 InstituteStage 模型中使用访问器:

public funcion getInstituteStageNameAttribute($value)
{
    return sprintf(
        '%s->%s->%s->%s',
        $this->branch->name,
        $this->version->name,
        $this->shift->name,
        $this->stage->name
    );
}

这样,当您尝试访问 Institute State 模型的 institute_stage_name 属性时,上面的函数就会被执行。

然后在你的控制器中你可以简单地做:

$stages = InstituteStage::where([
    ['stage_for', 'Student'],
    ['status', 'active']
])
->with('branch', 'version', 'shift', 'stage')
->get();

最后在你的刀片视图中:

@foreach ($stages as $stage)
    <option value="{{ $stage->id }}" {{ old('institute_stage_id') === $stage->id ? 'selected' : '' }} >{{ $stage->institute_stage_name }}</option>
@endforeach

您可以深入了解一些有用的方法,例如 documentation 中的访问器。

更新

如果您进一步想将查询移到控制器之外,我会亲自在模型中使用本地和动态范围(文档 here)。

为了获得最大的灵活性,我会在两个本地范围内将您需要的两个 where 条件分开:

public function scopeActive($query)
{
    return $query->where('status', 'active');
}

public function scopeFor($query, $type)
{
    return $query->with('branch', 'version', 'shift', 'stage')
        ->where('stage_for', $type);
}

然后您可以将这两种方法与查询构建器语法结合使用,如下所示:

$stages = InstituteStage::for('Student')->active()->get();

如果您在使用已定义的for 本地范围时始终需要活动阶段,则可以将-&gt;active() 方法调用移动到scopeFor 方法内:

public function scopeFor($query, $type)
{
    return $query->with('branch', 'version', 'shift', 'stage')
        ->where('stage_for', $type)
        ->active();
}

查询会变成:

$stages = InstituteStage::for('Student')->get();

使用查询范围的强大之处在于它们不会阻止您在它们之前/之后进一步应用任何查询构建器方法,因此您有一个通用方法以更简单的方式应用基本过滤,然后您可以进一步自定义(如果需要) 带有附加 wheres、joins 等的查询,最后得到结果。

更新:关于访问器的说明

您能解释一下我们是如何通过调用“institute_stage_name”来获取连接名称的,因为它没有显示在数组中吗?

这就是访问器的工作方式:您可以定义一个名为 getYourPropNameAttribute($value) 的方法,当您尝试访问其相关属性时,laravel 会自动调用该方法,在本例中为:$model-&gt;your_prop_name(请注意访问器函数名中的属性名)。

引用自文档:

要定义访问器,请在您的模型上创建一个getFooAttribute 方法,其中Foo 是您希望访问的列的“严格”大小写名称。

它是如何工作的代码方面
当您访问您的模型之一(都扩展了 laravel 的模型类)上的属性时,将执行以下函数:

  • __get 魔术方法 (source code) 将被执行并调用 getAttribute 函数 (source code)
  • getAttribute 将调用hasGetMutator (source code) 来检查您的模型类中是否存在名为get + ThePropYouAreAccessingName + Attribute 的方法
  • 如果您正在访问的属性具有访问器方法或者是模型的属性,则使用getAttributeValue 调用(在getAttribute 下方定义几行)检索其值。
  • 如果 mutator 存在,则框架会调用它,并将其值返回到您首先访问该属性的位置。

【讨论】:

  • 谢谢..这几乎就是我想要的..我已经读过关于突变的文章。却想不通。但是是否可以对其进行更多过滤。我的意思是,我正在寻找这样的方法 -----> InstituteStage::institute_stage_name() 。这将返回具有这些名称的所有行。所有这些条件也将包含在该方法中..
  • 但是你能解释一下我们是如何通过调用'institute_stage_name'来获取连接名称的,因为它没有显示在数组中。我没有得到这部分
  • 我再次更新以包含更多详细信息,如果您的疑问已解决,请告诉我
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-28
  • 2011-08-11
  • 2021-12-13
  • 1970-01-01
相关资源
最近更新 更多