论如何使Model变得Flexible
Opened this issue · 1 comments
marcus-ma commented
日常的MVC开发中,一般人都会习惯把大量的逻辑直接写在Controller当中,这样的后果是代码的阅读性很差。而好一点的developer会把跟DB交互的代码部分写在Model的方法里面,这样起码是个好的开始。
情景导入
假如现在有一个逻辑,把用户的Informations展示出来,而DB中User表里Gender字段是用1或者2来表示,你需要在View中渲染Data时显示对应的语义意思。一般的做法是
在View中使用模板标签(TP5)
{switch name="$user.gender"}
{case value="1" break="0"}male{/case}
{case value="2"}female{/case}
{default /}None
{/switch}
这样是可以实现,但若是要使用API式的交互呢?直接把Data传给前端让前端再处理吗?
或许有人会说:在Model写段转换逻辑好了。
在Model中写转换逻辑
class UserModel
{
//性别属性
public $gender = 1;
public function getGender()
{
switch ($this->gender){
case 1:
return 'male';
break;
case 2:
return 'female';
break;
default:
return 'None';
}
}
}
这样就行了吗?如果又有其他的属性字段要进行语义转换,那UserModel里就要写很多的function,如果也有其他的项目也需要这样的转换,也照样重写一次那些function吗?如此导致Model的结构就变得很重,相同的逻辑代码无法重用。
其实有一个好办法:使用`Trait`特性和`Presenter`扩展Model解耦和:
自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。
使用Trait特性和Presenter扩展Model
- Model
class UserModel
{
//使用trait
use PresentableTrait;
//指定所要调用的presenter
protected static $presenter = 'UserPresenter';
//测试属性
public $gender = 1;
}
- 定义一个trait,以便Model可以调用对应的Presenter
trait PresentableTrait
{
protected static $presenterInstance;
//单例模式,减少new的次数
public static function presenter()
{
if (!self::$presenterInstance){
self::$presenterInstance = new self::$presenter(new self);
}
return self::$presenterInstance;
}
}
- Presenter
class UserPresenter
{
protected $user;
//指定关联的Model
public function __construct(UserModel $user)
{
$this->user = $user;
}
//性别的语义转换
public function gender()
{
switch ($this->user->gender){
case 1:
return 'male';
break;
case 2:
return 'female';
break;
default:
return 'None';
}
}
}
- 方法调用
echo UserModel::presenter()->gender();
这样就可以减轻Model本身的结构,又可以实现一些逻辑代码的重用,使整个结构变得Flexible易于后期的扩展。
除了Presenter外,还可以用trait来解决PHP的单继承问题,此外将DB的查询写成Repository会让修改和测试更加容易
class UserRepository
{
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
//取出用户所有Data
public function getActiveAll()
{
return $this->user->all();
}
}
总结:好的Model结构
- Model本身只包含Table设置和关联关系设定
- 使用Trait特性和Presenter扩展Model解耦和
- 使用Trait特性线性继承解耦和
小记
最近看了**举办的LaravelConf的系列视频,感觉获益良多,见识了很多从来没见过的写法,原来PHP还有这么优雅的写法。同时也深深体会到Laravel这款框架的优雅性,有机会真得读读源码,增长点见识。
phenomLi commented
几时先学得你甘成功