制作一个自定义模型,该模型将从另一个模型中获取数据laravel 5.8

时间:2019-08-27 06:13:51

标签: laravel laravel-5 eloquent laravel-5.8

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

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

1 个答案:

答案 0 :(得分: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)中使用本地和动态范围。

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

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本地范围时始终需要活动阶段,则可以将->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->your_prop_name(请注意studly /访问者函数名称中属性名称的pascal大小写。)

文档引用:

  

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

它是如何工作的代码方式
当您访问其中一个模型的属性(全部扩展了laravel的模型类)时,将执行以下功能:

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