Php Laravel中的多态性?
例如,我的modelPhp Laravel中的多态性?,php,laravel,oop,polymorphism,Php,Laravel,Oop,Polymorphism,例如,我的modelMessage包含以下列: messages - id - body - type - created_at - updated_at 以及该控制器: class MessageController extends Controller { /** * Display the specified resource. * * @param \App\Message $message * @return \Illuminat
Message
包含以下列:
messages
- id
- body
- type
- created_at
- updated_at
以及该控制器:
class MessageController extends Controller
{
/**
* Display the specified resource.
*
* @param \App\Message $message
* @return \Illuminate\Http\Response
*/
public function show(Message $message)
{
switch ($message->type) {
case 'info':
$color = 'blue';
// updated - lots of code here!
break;
case 'warning':
$color = 'yellow';
// updated - lots of code here!
break;
.
.
.
case 'danger':
$color = 'red';
// updated - lots of code here!
break;
default:
$color = 'gray';
// updated - lots of code here!
}
return view('messages.show',compact(['message','color']));
}
}
正如你所看到的,我的问题是这个长开关。我试着搜索,发现多态性
可以帮助我避免这个长切换,但我没有找到如何实现它。我做了多少,我所有的搜索都以Laravel中的多态关系结束,这不是我的答案
你能帮我做点像这样的事吗:
class MessageController extends Controller
{
/**
* Display the specified resource.
*
* @param \App\Message $message
* @return \Illuminate\Http\Response
*/
public function show(Message $message)
{
$color = $message->[something?]->color();
return view('messages.show',compact(['message','color']));
}
}
更新:正如我在开头所写的,这只是一个示例,switch case块将包含更多的代码行。无需多态,只需在模型或配置中创建这样的数组:
$messageColors = [
"info"=>"blue",
.......
]
然后写下:
$color = $messageColors[$message->type];
我将创建一个包含常量的类:
<?php
namespace App\Constants;
class TextColor
{
const INFO = 'blue';
...
const DANGER = 'red';
}
// usage
$color = TextColor::INFO; // 'blue'
您可以使用某种“策略模式”来改进代码,创建一些服务来处理消息中每种类型(每种策略)的颜色计算,然后创建一个“delegator”服务,根据消息类型决定调用哪种服务
首先,您需要为所有计算器提供一个界面:
interface ColorCalculatorInterface
{
public function calculateColor(Message $message);
public function getSupportedMessageType();
}
然后,为每个策略提供一项服务:
class InfoColorCalculator implements ColorCalculatorInterface
{
public function getSupportedMessageType()
{
return 'info';
}
public function calculateColor(Message $message)
{
// lots of code here!
return 'blue';
}
}
class WarningColorCalculator implements ColorCalculatorInterface
{
public function getSupportedMessageType()
{
return 'warning';
}
public function calculateColor(Message $message)
{
// lots of code here!
return 'yellow';
}
}
// More calculators...
class DefaultColorCalculator implements ColorCalculatorInterface
{
public function getSupportedMessageType()
{
return 'default';
}
public function calculateColor(Message $message)
{
// lots of code here!
return 'grey';
}
}
最后是一个服务,它根据消息类型决定使用哪种策略(此代码可以直接进入控制器,但作为一个单独的服务更干净):
现在你的控制器薄多了
class MessageController extends Controller
{
/** @var ColorCalculator */
private $calculator;
public function show(Message $message)
{
$color = $this->calculator->calculateColor($message);
// do what you want with your color...
}
}
注意我不是一个Laravel开发者,而是一个Symfony开发者!我假设Laravel提供了一些方法来定义delegator服务并将所有计算器注册到其中,最后将该服务注入控制器。。。(Symfony有)最后,我从上面的示例中找到了答案,它对我的情况起到了作用:
\app\Message.php
\app\InfoMessage.php
\app\Http\Controllers\MessageController.php
谢谢你的回答。我认为你的问题与多态性无关。它与访问对象属性有关。@MarcinMagdziarz谢谢,但正如我在开头所写,它只是一个示例,switch case块将包含更多的代码行。谢谢,但正如我在开头所写,这只是一个示例,switch case块将包含更多的代码行。将它们保存在数据库或json文件中是无法避免的。谢谢,但正如我在开头所写的,这只是一个示例,switch case块将包含更多的代码行。是的,我理解,但是必须在某个地方进行类型和颜色之间的映射。您可以选择在第一个示例中的类中或在第二个建议中的表中执行此操作。。。静态方法。。。真正地无论如何,我很高兴你找到了一个至少对你有效的解决方案;)
class MessageController extends Controller
{
/** @var ColorCalculator */
private $calculator;
public function show(Message $message)
{
$color = $this->calculator->calculateColor($message);
// do what you want with your color...
}
}
class Message extends Model {
public static function color() {
// lots of code here!
return 'grey';
}
}
class InfoMessage extends Message {
public static function color() {
// lots of code here!
return 'blue';
}
}
class MessageController extends Controller {
public function show(Message $message) {
$color = $message->type ? $message->type::color() : $message->color();
// $message->type will be something like '\App\InfoMessage'
// so $message->type::color() will be equal to \App\InfoMessage::color()
return view('messages.show',compact(['message','color']));
}
}