优雅的组织Laravel项目结构

简介
Laravel默认的项目结构不太符合个人使用习惯,也不太适合大型项目使用。
原本把app/Http/目录下的Controllers目录丶Middleware目录丶Kernel.php均
移至app目录下了,但是有些快速生成Laravel的命令就使用不了了,不想自己去额外实现这些命令,
还是将其改回去了。由于动刀的仅有app目录,贴上目录结构:

 

 
├── Console
│   └── Kernel.php
├── Exceptions
│   ├── ApiException.php
│   ├── Handler.php
│   └── RequestInvalidException.php
├── Helper
├── Http
│   ├── Controllers
│   ├── Kernel.php
│   └── Middleware
├── Models
│   └── UserModel.php
├── Providers
│   ├── AppServiceProvider.php
│   ├── AuthServiceProvider.php
│   ├── BroadcastServiceProvider.php
│   ├── EventServiceProvider.php
│   └── RouteServiceProvider.php
├── Repositories
├── Requests
│   ├── Api
│   ├── BaseRequest.php
│   └── Mini
├── Services
│   ├── Api
│   ├── BaseService.php
│   └── Mini
└── Traits
    └── ApiResponseTrait.php

目录说明
新增加了目录Requests, Repositories, Services, Traits, Helper, Models目录。

Models
该目录下创建的类文件均是模型文件,仅仅定义模型还有其关联模型之间的关联,不进行任何其他的查询操作。
如UserModel.php:

 

 

 

 

 

 

 

 

<?php
 
 
namespace App\Models;
 
 
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
 
class UserModel extends Authenticatable implements JWTSubject
{
    use Notifiable;
 
    protected $table = 'users';
 
    /**
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];
 
 
    /**
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
 
 
    /**
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }
 
    /**
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
    
    // 关联用户详情表
    public function userInfo()
    {
        
    }
}

Requests

  • 该目录为表单验证类的目录,该目录下的Request类需要继承BaseRequest类, 然后通过注入到控制器中进行表单验证。

  • BaseRequest代码如下:

<?php
 
 
namespace App\Requests;
 
use App\Traits\ApiResponseTrait;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use App\Exceptions\RequestInvalidException;
 
 
class BaseRequest extends FormRequest
{
    use ApiResponseTrait;
 
    /**
     * 默认允许访问, 权限控制中间件已经进行过滤了!
     * @return bool
     */
    public function authorize()
    {
        return true;
    }
    
    // 验证失败抛接口异常。
    public function failedValidation(Validator $validator)
    {
        $error = $validator->errors()->first();
        throw new RequestInvalidException($error, 10000);
    }
}
  • LoginRequest.php代码如下:
<?php
 
 
namespace App\Requests\Api\User;
 
 
use App\Requests\BaseRequest;
 
class LoginRequest extends BaseRequest
{
    public function rules()
    {
        return [
            'username' => 'required',
            'password' => 'required',
        ];
    }
 
    public function messages()
    {
        return [
            'username.required' => '账号必填',
            'password.required' => '密码必填',
        ];
    }
}
  • 在控制器中使用LoginRequest, 如:
    // 用户登录
    public function login(LoginRequest $request)
    {
        //  $request->validated()这里拿到的数据即是验证成功后的数据。
        return $this->service->login($request->validated());
    }
 

Repositories

该目录下的类文件作用是进行数据的操纵(增删改查), 通过依赖注入方式引入模型类进行操作。

UserRepository代码:

<?php
 
 
namespace App\Repositories;
 
 
use App\Models\UserModel;
 
class UserRepository
{
    protected $model;
    
    public function __construct(UserModel $model)
    {
        $this->model = $model;
    }
    
    
    public function getUserById($id)
    {
        return $this->model->find($id);
    }
}

Services

该目录下的类文件主要用于业务逻辑的处理,通过注入Repository类进行数据操纵, 该目录下的Service都必须继承一个基类BaseService:

 
<?php
 
 
namespace App\Services;
 
 
use App\Traits\ApiResponseTrait;
 
 
/**
 * Class BaseService
 * @package App\Services
 */
class BaseService
{
    use ApiResponseTrait;
}

处理用户相关业务逻辑的UserService.php代码如下:

<?php
 
 
namespace App\Services\Api;
 
 
use App\Repositories\UserRepository;
use App\Services\BaseService;
 
 
class UserService extends BaseService
{
 
    protected $repository;
    
    public function __construct(UserRepository $repository)
    {
        $this->repository = $repository;
    }
 
    /**
     * 用户登录
     * @param $params
     * @return false|string
     */
    public function login($params)
    {
        // 这里仅作演示,不必在意细节
        return $this->repository->getUserById($params['id']);
    }
 
    /**
     * 用户注销
     */
    public function logout()
    {
        return $this->data(true, '注销成功');
    }
}

Traits

该目录下主要定义一些Trait,提高代码复用率。 如ApiResponseTrait.php代码:

<?php
 
 
namespace App\Traits;
 
 
/** 接口返回格式定义
 * Class ApiResponseTrait
 * @package App\Traits
 */
trait ApiResponseTrait
{
    /**
     * 返回成功数据
     * @param $data
     * @param string $msg
     * @return false|string
     */
    public function data($data, $msg='')
    {
        $resp = [
            'status' => 1,
            'data'=>$data,
            'msg' => $msg,
            'errno' => 0
        ];
 
        return response()->json($resp);
    }
 
    /**
     * 返回错误信息
     * @param $errno
     * @param string $msg
     * @return false|string
     */
    public function error($errno, $msg='')
    {
        $resp = [
            'status' => 0,
            'errno' => $errno,
            'data' => [],
            'msg'  => $msg,
        ];
        return response()->json($resp);
    }
}

Helper

该目录也是为了提高代码复用率,不过该文件夹下定义的是一些自定义函数。

Controllers

该目录下有两个子目录ApiMiniApiPC端接口, Mini是小程序端接口。

贴上一个控制器代码:

<?php
 
 
namespace App\Http\Controllers\Api;
 
 
use App\Http\Controllers\Controller;
use App\Requests\Api\User\LoginRequest;
use App\Services\Api\UserService;
 
/**
 * 用户相关模块
 * Class UserController
 * @package App\Http\Controllers\Api
 */
class UserController extends Controller
{
    public function __construct(UserService $service)
    {
        $this->service = $service;
    }
 
    // 用户登录
    public function login(LoginRequest $request)
    {
        return $this->service->login($request->validated());
    }
    
}

可以看到一个控制器方法仅有一行代码。

说明
引进Service和Repository层精简控制器代码,提高了代码的可读性。
Trait和Helper提高代码复用率,且方便集中管理。
通过依赖注入避免了new的使用, Laravel会递归的拿构造函数和参数进行注入实例。

 

 

 


————————————————
版权声明:本文为CSDN博主「ClassmateLin」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ClassmateLin/article/details/104324593

posted @ 2020-02-28 16:58  搬砖小伙子  阅读(703)  评论(0)    收藏  举报