«
基础API开发Laravel项目结构

时间:2021-7-17    作者:网络剑客    分类: php


简介

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

该目录下有两个子目录Api和Mini, Api是PC端接口, 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会递归的拿构造函数和参数进行注入实例。

标签: laravel