Ali*_*ice 6 php model view laravel laravel-blade
我有一个 Laravel 7 项目,需要在显示之前将大量数据从模型转换为视图。
我想过使用Laravel Accessors并直接在我的blade.php 文件中使用它们。
但是当我处理完一个简单的 html 表时,我查看了我的代码,我认为访问器太多了,甚至其中一些访问器的名称难以阅读。
@foreach($races as $race)
<tr>
<td>{{ $race->display_dates }}</td>
<td>{{ $race->display_name }}</td>
<td>{{ $race->type->name }}</td>
<td>{{ $race->display_price }}</td>
<td>{{ $race->display_places }}</td>
<td>{{ $race->online_registration_is_open ? 'Yes' : 'No' }}</td>
</tr>
@endforeach
Run Code Online (Sandbox Code Playgroud)
public function show(Group $group)
{
$races = $group->races;
$races->loadMissing('type'); // Eager loading
return view('races', compact('races'));
}
Run Code Online (Sandbox Code Playgroud)
// Accessors
public function getOnlineRegistrationIsOpenAttribute()
{
if (!$this->online_registration_ends_at && !$this->online_registration_starts_at) return false;
if ($this->online_registration_ends_at < now()) return false;
if ($this->online_registration_starts_at > now()) return false;
return true;
}
public function getNumberOfParticipantsAttribute()
{
return $this->in_team === true
? $this->teams()->count()
: $this->participants()->count();
}
// Accessors mainly used for displaying purpose
public function getDisplayPlacesAttribute()
{
if ($this->online_registration_ends_at < now()) {
return "Closed registration";
}
if ($this->online_registration_starts_at > now()) {
return "Opening date: " . $this->online_registration_starts_at;
}
return "$this->number_of_participants / $this->max_participants";
}
public function getDisplayPriceAttribute()
{
$text = $this->online_registration_price / 100;
$text .= " €";
return $text;
}
public function getDisplayDatesAttribute()
{
$text = $this->starts_at->toDateString();
if ($this->ends_at) { $text .= " - " . $this->ends_at->toDateString(); }
return $text;
}
public function getDisplayNameAttribute()
{
$text = $this->name;
if ($this->length) { $text .= " $this->length m"; }
if ($this->elevation) { $text .= " ($this->elevation m)"; }
return $text;
}
Run Code Online (Sandbox Code Playgroud)
这段代码正在运行,但我认为它有很多缺点:可读性、错误是可能的,例如,如果name
我在getDisplayNameAttribute
这里创建访问器时关联的数据库表有一个列。
这只是一个开始,我想其他视图我还需要 30-40 个访问器......此外,我需要多次使用其中的一些,例如getDisplayNameAttribute
可以在常规页面和管理页面中使用(也许更多)。
我还查看了JsonResource和ViewComposer,但JsonResource
似乎有APIs
一段时间ViewComposer
似乎特别适用于Views
.
我还考虑过在访问器前添加类似acc_
减少现有 db 列错误的内容:
public function getAccDisplayNameAttribute() { ... };
Run Code Online (Sandbox Code Playgroud)
但我真的不认为这是一个解决方案,我什至不确定我在做什么是对还是错。我还通过互联网搜索了最佳实践,但没有成功。
小智 3
您可以创建一个专门处理转换的类。然后,您可以在模型构造函数中加载此类的实例。\n如果您愿意,您还可以使访问器类使用 PHP magic getter。
\n\nclass RaceAccessors {\n // The related model instance\n private $model;\n\n // Already generated results to avoid some recalculations\n private $attributes = [];\n\n function __construct($model)\n {\n $this->model = $model;\n }\n\n // Magic getters\n public function __get($key)\n {\n // If already called once, just return the result\n if (array_key_exists($key, $this->attributes)) {\n return $this->attributes[$key];\n }\n\n // Otherwise, if a method with this attribute name exists\n // Execute it and store the result in the attributes array\n if (method_exists(self::class, $key)) {\n $this->attributes[$key] = $this->$key($value);\n }\n\n // Then return the attribute value\n return $this->attributes[$key];\n }\n\n // An example of accessor \n public function price()\n {\n $text = $this->model->online_registration_price / 100;\n $text .= " \xe2\x82\xac";\n return $text;\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\nclass Race {\n // The Accessors class instance\n public $accessors;\n\n function __construct()\n {\n $this->accessors = new \\App\\Accessors\\RaceAccessors($this);\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n@foreach($races as $race)\n<tr>\n <td>{{ $race->accessors->price }}</td>\n [...]\n</tr>\n@endforeach\n
Run Code Online (Sandbox Code Playgroud)\n\n我没有在这里为变量设置类型$model
,因为您可以将相同的accessors class
类型用于需要以与此访问器类相同的方式转换某些字段的其他模型。
例如,价格访问器可以适用于 Race(在您的情况下),但它也可以适用于其他模型,这样您就可以想象创建许多模型使用的访问器组,而无需更改太多代码来处理它。
\n