Laravel 项目开发规范

Laravel 项目开发规范

目录

优势

规范有以下优点:

  • 高效编码:避免了过多的选择造成的『决策时间』浪费
  • 风格统一 : 最大程度统一了开发团队成员代码书写风格和思路,代码阅读起来如出一辙
  • 减少错误 : 减小初级工程师的犯错几率。

开发哲学

开发中请把其当做指明灯,来指引你做决策:

  • DRY:「Don’t Repeat Yourself」不写重复的逻辑代码
  • 约定俗成:优先选择框架提倡的做法,不过度配置
  • KISS:「Keep it Simple, Stupid」提倡简单易读的代码,不写高深、晦涩难懂的代码,不过度设计
  • 主厨精选: 让有经验的人来为你选择方案,不独创方案
  • 官方提倡:优先选择官方推崇的方案

设计理念

以下是一些优秀的『程序设计理念』:

  • MVC :Model,View,Controller,以MVC为核心,严格控制 Controller 的可读性和代码行数
  • Resutful:利用『资源化概念』和标准的 HTTP 动词来组织你的程序

开发和线上环境

一般情况下,一个项目 应该 有以下三个基本的项目环境:

  • Local:开发环境
  • Staging:线上测试环境
  • Production:线上生产环境

开发专用扩展包

我们都知道 Laravel 扩展包的注册会对应用造成消耗。

有一些扩展包是开发环境中专用,生产环境中并不会使用到。

为了避免无用的负载, 必须严格控制其安装和加载。

安装开发专用扩展包时 必须 使用 --dev 参数,如:

1
composer require laracasts/generators --dev

开发专用的 provider 绝不config/app.php 里面注册

必须app/Providers/AppServiceProvider.php 文件中使用如以下方式:

1
2
3
4
5
6
public function register()
{
if ($this->app->environment() == 'local') {
$this->app->register('Laracasts\Generators\GeneratorsServiceProvider');
}
}

辅助函数

存放位置

必须 把所有『自定义辅助函数』存放于 bootstarp 文件夹中。

并在 bootstrap/app.php 最顶部进行加载。

1
2
3
4
5
<?php

require __DIR__ . '/helpers.php';

...

路由

路由器要保证干净整洁, 绝不 防止除路由配置以外的其他的程序逻辑。

资源命名使用复数

Restful 路由

必须 优先使用 Restful 路由,配合资源控制器使用。

由资源控制器处理的行为:

动词路径行为(方法)路由名称注释
GET/photosindexphotos.index首页
GET/photos/createcreatephotos.create创建页面
POST/phototsstorephotos.store数据入库
GET/photos/{id}showphotos.show个人展示页
GET/photos/{id}/editeditphotos.edit个人编辑页
PUT / PATCH/photos/{id}updatephotos.update个人信息更新
DELETE/photos/{id}destoryphotos.destory个人信息删除
全局路由参数

出于安全考虑, 应该 使用全局路由器参数限制。

必须RouteServiceProvider 文件的 boot 方法里定义模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 定义你的路由模型绑定,模式过滤器等。
*
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function boot(Router $router)
{
// 路由参数限制
$router->pattern('id', '[0-9]+');
// 模型绑定
Route::bind('user_name', function ($value) {
return User::where('name', $value)->first();
});

parent::boot($router);
}

模式一旦被定义,遍会自动应用到所有使用该参数名称的路由上:

1
2
Route::get('users/{id}', 'UsersController@show');
Route::get('photos/{id}', 'PhotosController@show');

只有 id 为数字时,才会路由到控制器方法中,否则 404 错误。

获取 URL

获取 URL 必须 遵循以下优先级:

  1. $model->link()
  2. route 方法
  3. url 方法

在 Model 中创建 link() 方法:

1
2
3
4
5
6
public function link($params = [])
{
$params = array_merge([$this->id], $params);

return route('models.show', $params);
}

所有单个模型数据链接使用:

1
2
3
$model->link();
// 或者添加参数
$model->link($params = ['source' => 'list'])

『单个模型 URI』经常会发生变化,这样做将会让程序更加灵活。

除了『单个模型 URI』,其他路由 必须 使用 route 来获取 URL:

1
$url = route('profile', ['id' => 1]);

无法使用 route 的情况下, 可以 使用 url 方法来获取 URL:

1
url('profile', [1]);

数据模型

模型命名使用 单数

放置位置

所有的数据模型文件,都 必须 存放在:app/Models/ 文件夹中。

命名空间:

1
namespace App\Models;
User.php

Laravel 默认安装会把 User 模型存放在 app/User.php必须 移动到 app/Models 文件夹中,并修改命名空间为 App/Models

为了不破坏原来的逻辑点,必须全局搜索 App/User 并替换为 App/Models/User

使用基类

所有的 Eloquent 数据模型必须 继承统一的基类 App/Models/Model ,此基类存放位置为 /app/Models/Model.php,内容参考以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model as EloquentModel;

class Model extends EloquentModel
{
public function scopeRecent($query)
{
return $query->orderBy('created_at', 'desc');
}
}
命名规范

数据模型相关命名规范:

  • 数据模型类名 必须 为「单数」, 如:App\Models\Photo
  • 类文件名 必须 为「单数」,如:app/Models/Photo.php
  • 数据库表名字 必须 为「复数」,多个单词情况下使用「Snake Case」 如:photos, my_photos
  • 数据库表迁移名字 必须 为「复数」,如:2014_08_08_234417_create_photos_table.php
  • 数据填充文件名 必须 为「复数」,如:PhotosTableSeeder.php
  • 数据库字段名 必须 为「Snake Case」,如:view_count, is_vip
  • 数据库表主键 必须 为「id」
  • 数据库表外键 必须 为「resource_id」,如:user_id, post_id
  • 数据模型变量 必须 为「resource_id」,如:$user_id, $post_id

控制器

控制器命名用 复数

必须 优先使用 Restful 资源控制器。

保持短小精练

必须 保持控制器文件代码行数最小化,还有可读性。

  • 不应该 为「方法」书写注释,这要求方法取名要足够合理,不需要过多注释;
  • 应该 为一些复杂的逻辑代码块书写注释,主要介绍产品逻辑 - 为什么要这么做。
  • 不应该 在控制器中书写「私有方法」,控制器里 应该 只存放「路由动作方法」;
  • 绝不 遗留「死方法」,就是没有用到的方法,控制器里的所有方法,都应该被使用到,否则应该删除;
  • 绝不 在控制器里批量注释掉代码,无用的逻辑代码就必须清除掉。

视图

优先使用 Blade

视图文件 必须 优先考虑使用 .blade.php 后缀来指定使用 Blade 模板引擎。

保持目录清晰
  • layouts - 页面布局文件 必须 放置于此目录下;
  • common - 存放页面通用元素;
  • pages - 简单的页面存放文件夹,如:about、contact 等;
  • resources - 对应 Restful 路由的资源路径名称,以 URI photos/create 为例,对应 create.blade.php文件,存放在文件夹 photos 下。

必须 避免在 resources/views 目录下直接放置视图文件。

局部视图

局部视图文件 必须 使用 _ 前缀来命名,如:photos/_upload_form.blade.php

视图命名要释义

为了和 Restful 路由器和资源控制器保持一致,视图命名也 必须 使用资源视图的命名方式。以 photos 为例:

  • photos/index.blade.php
    • 内容列表视图
    • 对应路由器 /photos,命名 photos.index
    • 控制器方法 PhotosController@index
create_and_edit 视图

很多情况下,创建和编辑视图里的页面结构接近相似,在这种情况下,应该 使用 create_and_edit 视图。以 photos 为例:

  • PhotosController@create - 对应视图:/photos/create_and_edit.blade.php
  • PhotosController@edit - 对应 视图:/photos/create_and_edit.blade.php

表单验证

必须 使用 表单请求 - FormRequest 类来处理控制器里的表单验证。

绝不 使用 authorize() 方法来做用户授权,用户授权我们会单独使用 Policy 授权策略 来实现。

使用基类

所有 FormRequest 表验证类 必须 继承 app/Http/Requests/Request.php 基类。

基类文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class Request extends FormRequest
{
public function authorize()
{
// Using policy for Authorization
return true;
}
}
验证类命名

命名使用 单数

FormRquest 表验证类 必须 遵循 资源控制器 方式进行命名,photos 对应 app/Http/Requests/PhotoRequest.php

类文件参考

FormRequest 表验证文件参考以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

namespace App\Http\Requests;

class PhotoRequest extends Request
{
public function rules()
{
switch($this->method())
{
// CREATE
case 'POST':
{
return [
// CREATE ROLES
];
}
// UPDATE
case 'PUT':
case 'PATCH':
{
return [
// UPDATE ROLES
];
}
case 'GET':
case 'DELETE':
default:
{
return [];
};
}
}

public function messages()
{
return [
// Validation messages
];
}
}
授权策略
使用基类

所有 Policy 授权策略类 必须 继承 app/Policies/Policy.php 基类。

基类文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace App\Policies;

use Illuminate\Auth\Access\HandlesAuthorization;

class Policy
{
use HandlesAuthorization;

public function __construct()
{
//
}

public function before($user, $ability)
{
if ($user->isAdmin()) {
return true;
}
}
}
授权策略命名

命名使用 单数

Policy 授权策略类 必须 遵循 资源路由 方式进行命名,photos 对应 /app/Policies/PhotoPolicy.php

类文件参考

Policy 授权策略文件内容参考以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

namespace App\Policies;

use App\Models\User;
use App\Models\Photo;

class PhotoPolicy extends Policy
{
public function update(User $user, Photo $photo)
{
return $user->isAuthorOf($photo);
}

public function destroy(User $user, Photo $photo)
{
return $user->isAuthorOf($photo);
}
}
自动判断授权策略

应该 使用 自动授权策略方法,这样控制器和授权类的方法名就统一起来了。

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 更新指定的文章。
* @param int $id
* @return Response
*/
public function update($id)
{
$post = Post::findOrFail($id);
// 会自动调用 `PostPolicy` 类中的 `update` 方法。
$this->authorize($post);
// 更新文章...
}

Auth 中间件

Auth 中间件 必须 书写在控制器 __construct 方法中,并且 必须 使用 except 黑名单进行过滤。

这样当你新增控制器方法时,默认是安全的。

1
2
3
4
5
6
public function __construct()
{
$this->middleware('auth', [
'except' => ['show', 'index']
]);
}
感谢您的阅读,本文由 Summer 原创提供。如若转载,请注明出处:Summer(https://laravel-china.org/docs/laravel-specification/5.5/whats-the-use-of-standards/510
初次接触 Yii
Mac命令行终端下使用shadowsocks翻墙