我有一个模型,该模型存储各种表的外键数据。这是模型的详细信息:
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
答案 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
将调用hasGetMutator
(source code)来检查模型类中是否存在名为get + ThePropYouAreAccessingName + Attribute
的方法getAttributeValue
调用(在getAttribute
下定义几行)检索其值。