将 class 名称传递给 Laravel 中的视图的常见做法
Common practice to pass class names to views in Laravel
我有一个将模型名称和 class 名称传递给视图的控制器方法。这些 class 然后在另一个控制器方法中实例化。在这种情况下,我使用 Laravel Excel 包。
public function index()
{
$exports = [
'Model name 1' => TestExport::class,
'Model name 2' => AnotherExport::class
];
return view('export', compact('exports'));
}
public function download(string $collection)
{
return Excel::download(new $collection(), 'Export.xlsx');
}
然后我的视图文件重定向到具有特定 class 名称的 download
控制器方法。
@foreach($exports as $name => $collection)
<a href="{{ action('ExportController@download', $collection) }}">Download</a>
@endforeach
因为我正在学习设计模式,并且注意到它会违反 DRY 规则,所以我不想要另一个控制器方法或我下载的每个不同的 Excel 文件。
这是好的做法还是可以做得更好?
在我看来,您的解决方案是将视图逻辑与控制器逻辑混合在一起。
- 控制器应该处理传入的请求,获取正确的数据,然后形成响应。
- 视图应根据给定数据处理任何逻辑,以便呈现输出页面。
在您的情况下,您传递给视图的数据不会被检索,它只是一个静态列表,也可以保存在视图中。更好的解决方案是:
- 在您的 blade 模板中有一个路由列表(不是 类 的列表)并对其进行迭代。
- 如果路由列表不是那么长,请对整个列表进行硬编码,而不是使其动态化。
这样做的主要原因是为了防止大量 'magic' 代码。例如,在您的 blade 模板中,您希望 exports
是一个包含 类 列表的数组,它必须是控制器并且必须具有 download
函数,否则代码中断。
解决方案 1 的示例类似于:
<?php
// You could consider moving $routes to the controller
$routes = [
action('ExportController@download', TestExport::class),
action('ExportController@download', AnotherExport::class),
];
@foreach($routes as $route)
<a href="{{ $route }}">Download</a>
@endforeach
您可以使 $exports
对两种方法通用,而不接受请求中的 class 名称。
const EXPORTS = [
'export_name_1' => TestExport::class,
'export_name_2' => AnotherExport::class,
];
public function index()
{
return view('export', compact(self::EXPORTS));
}
public function download(string $collection)
{
if (!isset(self::EXPORTS[$collection]) {
return 'error';
}
$className = self::EXPORTS[$collection];
return Excel::download(new $className(), 'Export.xlsx');
}
永远不要让请求操作破坏您的代码。对于 export_name
,您可以简单地使用整数或数组简单索引。
查看
@foreach($exports as $name => $collection)
<a href="{{ action('ExportController@download', $name)}}">Download</a>
@endforeach
我有一个将模型名称和 class 名称传递给视图的控制器方法。这些 class 然后在另一个控制器方法中实例化。在这种情况下,我使用 Laravel Excel 包。
public function index()
{
$exports = [
'Model name 1' => TestExport::class,
'Model name 2' => AnotherExport::class
];
return view('export', compact('exports'));
}
public function download(string $collection)
{
return Excel::download(new $collection(), 'Export.xlsx');
}
然后我的视图文件重定向到具有特定 class 名称的 download
控制器方法。
@foreach($exports as $name => $collection)
<a href="{{ action('ExportController@download', $collection) }}">Download</a>
@endforeach
因为我正在学习设计模式,并且注意到它会违反 DRY 规则,所以我不想要另一个控制器方法或我下载的每个不同的 Excel 文件。
这是好的做法还是可以做得更好?
在我看来,您的解决方案是将视图逻辑与控制器逻辑混合在一起。
- 控制器应该处理传入的请求,获取正确的数据,然后形成响应。
- 视图应根据给定数据处理任何逻辑,以便呈现输出页面。
在您的情况下,您传递给视图的数据不会被检索,它只是一个静态列表,也可以保存在视图中。更好的解决方案是:
- 在您的 blade 模板中有一个路由列表(不是 类 的列表)并对其进行迭代。
- 如果路由列表不是那么长,请对整个列表进行硬编码,而不是使其动态化。
这样做的主要原因是为了防止大量 'magic' 代码。例如,在您的 blade 模板中,您希望 exports
是一个包含 类 列表的数组,它必须是控制器并且必须具有 download
函数,否则代码中断。
解决方案 1 的示例类似于:
<?php
// You could consider moving $routes to the controller
$routes = [
action('ExportController@download', TestExport::class),
action('ExportController@download', AnotherExport::class),
];
@foreach($routes as $route)
<a href="{{ $route }}">Download</a>
@endforeach
您可以使 $exports
对两种方法通用,而不接受请求中的 class 名称。
const EXPORTS = [
'export_name_1' => TestExport::class,
'export_name_2' => AnotherExport::class,
];
public function index()
{
return view('export', compact(self::EXPORTS));
}
public function download(string $collection)
{
if (!isset(self::EXPORTS[$collection]) {
return 'error';
}
$className = self::EXPORTS[$collection];
return Excel::download(new $className(), 'Export.xlsx');
}
永远不要让请求操作破坏您的代码。对于 export_name
,您可以简单地使用整数或数组简单索引。
查看
@foreach($exports as $name => $collection)
<a href="{{ action('ExportController@download', $name)}}">Download</a>
@endforeach