简介
MVC(Model-View-Controller) 是 PHP 开发中常用的架构模式,大部分项目构建都是基于这种模式。
- 模型 Model – 连接和操作数据库数据。
- 控制器 Controller - 负责响应用户请求、准备数据,以及决定如何展示数据。
- 视图 View – 负责渲染数据,通过 HTML 方式呈现给用户。
Model 操作数据Controller 控制器View 视图
本文 PHP 演示均使用 ThinkPHP6.0
模型 Model 使用习惯
项目中一般设置 后台(Admin)、Web端(Index)、接口(Api) 三个大的模块。往往 Web端(Index) 和 接口(Api) 会共用一个 Model 层,而 后台(Admin) 因为涉及大量增删改查的动作,我一般会给 后台(Admin) 单独创建一个 Model 层。
# 后台使用namespace app\Model\admin;# web、Api使用namespace app\Model;
在 ProductModel 中创建几个常用方法:
<?phpnamespace app\Model\admin;use think\Db;class ProductModel{/*** Get Product* 获取单个产品* @param array $params* @return array*/public function getProduct($params = []) {}/*** Get Products* 获取多个产品* @param array $params* @return array*/public function getProducts($params = []) {}/*** Create Product* 创建产品* @param array $params* @return array*/public function create($params = []) {}/*** Update Product* 更新产品* @param array $params* @return array*/public function update($params = [], $id) {}}
需要注意,方法中使用传递数组 $params = [] 的方式,这样在项目后期可以提升代码的观赏度,避免出现以下情况:
public function getProducts($id, $category_id = '', $paginate = 1, $barand_id = '', ...) {}
当存在少量参数时,在当前方法中处理参数:
public function getProduct($params = []){$query = Db::name('product');if (isset($params['id'])) $query->where('id', $params['id']);if (isset($params['status'])) $query->where('status', $params['status']);$product = $query->find();return $product;}
当存在大量参数时,可使用 private 辅助方法处理参数:
public function getProducts($params = []){$query = Db::name('product');$this->setGetProductsParams($query, $params);$product = $query->find();return $product;}private function setGetProductsParams($query, $params = []){if (isset($params['category_id'])) $query->where('category_id', $params['category_id']);if (isset($params['brand_id'])) $query->where('brand_id', $params['brand_id']);if (isset($params['status'])) $query->where('status', $params['status']);if (isset($params['type'])) $query->where('type', $params['type']);}
有时会需要在某个方法中调取不同类型的数据,即需要支持数组、又需要支持对象,或是框架带分页数据。这里我常使用多个方法处理,并不是在一个方法中通过不同参数返回不同类型的数据。
/*** Get Products* 获取多个产品* @param array $params* @return array*/public function getProducts($params = []){$products = Db::name('product')->select()->toArray();return $products;}/*** Get Products* 获取多个产品* @param array $params* @return object*/public function getProductsObject($params = []){$products = Db::name('product')->select();return $products;}/*** Get Products* 获取多个产品* @param array $params* @return object 分页*/public function getProductsPage($params = []){$products = Db::name('product')->paginate();return $products;}
控制器 Controller 使用习惯
增删改查常用于后台,我习惯定义的方法名:
# 列表页public function index() {}# 新增页public function create() {}# 保存数据public function store() {}# 编辑页public function edit() {}# 更新数据public function update() {}# 非物理删除数据public function delete() {}# 物理删除数据public function destory() {}# 其它方法......
MVCR
有些项目一般选择在模型 Model 与控制器 Controller 之间加一层逻辑处理的模块,我习惯使用 R(Repository:仓库、储藏室)命名(网上也有说使用 I 命名)。
通俗点讲,就是保持了 Model 的共用性、整洁性和 Controller 的整洁性,在 Repository 中处理较为复杂的逻辑。下面我们用两个示例来简单说明下 Repository 的作用。
1,查询产品,并修改结果数据格式:
在 ProductModel 中创建查询多个产品的方法:
<?phpnamespace app\Model\admin;use think\Db;class ProductModel{public function getProducts() {}}
通常逻辑我们会在控制器中直接调用该方法。这里我们改变下思路使用 ProductRepository 来获取数据,并修改产品创建时间格式:
<?phpnamespace app\Repository\admin;use app\Model\admin\ProductModel;class ProductRepository{public function getProducts(){$products = app(ProductModel::class)->getProducts();foreach ($products as $key => $value) {$products[$key]['create_time'] = date('Y-m-d', $value['create_time']);}}}
最后,在控制器中使用 ProductRepository 中的 getProducts 方法。
2,用户登录: UserModel 中查询,更新方法:
<?phpnamespace app\Model\admin;use think\Db;class UserModel{public function getUser($params = []) {}public function update($params = [], $id) {}}
UserRepository 中登录方法:
<?phpnamespace app\Repository\admin;use app\Model\admin\UserModel;class UserRepository{public function login($username, $password){// 验证信息$user = app(UserModel)->getUser(['username' => $username, 'password' => $password]);if (!$user) return arrayFailed('login failed');// 登录成功后续操作app(UserModel)->update(['last_login_time' => time()], $user->id);}}
UserController 中使用 UserRepository 中的 login 方法:
<?phpnamespace app\Repository\api;use think\Request;use app\Model\admin\UserRepository;class UserController{public function login(Request $request){$res = app(UserRepository::class)->login($request->username, $request->password);}}
上面两个示例简单展示了在 Repository 中,处理结果数据与操作业务逻辑。这里也建议项目中加入 Repositoy 层,在保持代码整洁的同时,也有灵活的扩展性。
