aogg
9/29/2018 - 2:52 AM

laravel扩展系统类库相关

laravel类库相关

laravel类库相关

  • SingleApiControllerTrait.php是给控制提供增删改查功能
  • bootstrap-app.php文件是,让env支持后缀切换,根据header或者环境变量

HttpCacheMiddleware

http的cache,用于http的缓存 例子: 在kernel中添加:

    protected $routeMiddleware = [
        'http.cache' => Middleware\HttpCacheMiddleware::class,
    ];

在路由中添加:

Route::group(['prefix' => 'soft'], function ($router){
    /* @var \Illuminate\Routing\Router $router */

    $router->get('stock/capture/img/{code}', 'HqController@stockCaptureImg')
        ->middleware(['http.cache:900,true']);
});
<?php
/**
 * User: aozhuochao
 * Date: 2019/9/17
 */

namespace App\Library\Vendor\Laravel;

/**
 * 自动添加前缀的DB::raw()
 */
class AutoPrefixExpression extends \Illuminate\Database\Query\Expression
{
    /**
     * @var \Illuminate\Database\Eloquent\Model
     */
    protected $model;

    /**
     * Create a new raw query expression.
     *
     * @param string $value
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $type 1为不是必须要`的,2为别名必须`包围加强替换
     */
    public function __construct($value, $model, $type = 1)
    {
        $this->model = $model;
        $this->setValue($value, $type);
    }

    public function getModelPrefix()
    {
        return $this->model->getConnection()->getTablePrefix();
    }

    /**
     * @param mixed $value
     * @param $type
     * @return AutoPrefixExpression
     */
    public function setValue($value, $type)
    {
        // 自动拼接前缀
        if ($type === 2){
            $value = preg_replace('/`([a-z_]+)`(\.[a-z_*]+)/i', $this->getModelPrefix() . '`\1`\2', $value);
        }else{
            $value = preg_replace('/(`?)([a-z_]+)\1(\.[a-z_*]+)/i', $this->getModelPrefix() . '\1\2\1\3', $value);
        }

        $this->value = $value;

        return $this;
    }
}
<?php
/**
 * Created by PhpStorm.
 * User: code
 * Date: 2018-12-20
 * Time: 11:24
 */

namespace App\Console\Commands;

use App\Listeners\SaveSqlListener;

/**
 * 系统命令类库,实现多方法
 */
class Command extends \Illuminate\Console\Command
{

    protected $description = '系统命令类库,实现多方法';

    protected $signature = 'command:helper';

    public function __construct()
    {
        $this->signature .= ' {method? : 执行的方法}';
        $this->signature .= ' {--arg=* : 方法的额外参数}';
        $this->signature .= ' {--s|sql : 打印sql}'; // -s或者--sql

        parent::__construct();
    }


    /**
     * 执行入口
     */
    public function handle()
    {
        $args = $this->option('arg'); // 数组
        $method = $this->argument('method');

        if (empty($method)) { // 必传
            $this->error('请指定执行的方法!');
            return;
        }

        /**
         * 开启sql记录
         */

        // 打印sql,需要额外记录类库
        if ($this->option('sql') && class_exists(SaveSqlListener::class)) {
            SaveSqlListener::setAutoSendCallback(function ($data){
                $this->info(json_encode($data));
            });
            SaveSqlListener::setCloseBool(false);
        }

        call_user_func_array([$this, $method], $args);
    }
}
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    use \Flugg\Responder\Exceptions\ConvertsExceptions; // 使用flugger/laravel-responder扩展


    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param  \Exception  $exception
     * @return void
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        static $convertBool = false; // 是否经过转换

        $apiExceptionArr = [
            // jwt自带中间件报错
            \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException::class => \Flugg\Responder\Exceptions\Http\UnauthenticatedException::class,
        ];
        if ($convertBool || $request->wantsJson() || array_key_exists(get_class($exception), $apiExceptionArr)) {
            $convertBool = true;
            // 转换异常
            $this->convert($exception, $apiExceptionArr);
            $this->convertDefaultException($exception);

            if ($exception instanceof \Flugg\Responder\Exceptions\Http\HttpException) {
                return $this->renderResponse($exception);
            }
        }

        return parent::render($request, $exception);
    }
}
<?php


namespace App\Library\Traits;


use Illuminate\Support\Str;

/**
 * 处理model类名
 * 如:
 * 1、支持model类名后面带Model的情况,下的hasMany自动拼接字段名
 */
trait HandleModelClassNameAtRelationTrait
{
    public function getForeignKey()
    {
        return Str::snake(preg_replace("/Model$/", "", class_basename($this))).'_'.$this->getKeyName();
    }
}
<?php
/**
 * User: aozhuochao
 * Date: 2019/9/18
 */

namespace App\Library\Tools;


use Illuminate\Database\Eloquent\Builder;

/**
 * 处理分页和导出
 *
 * 可用Facade门面系统实现单例
 */
class ModelPaginateExportTool
{
    /**
     * 指定分页大小的名称
     *
     * @var string
     */
    protected $prePageName = 'page_size';

    /**
     * 分页名称
     *
     * @var string
     */
    protected $pageName = 'page';

    /**
     * 默认分页大小
     *
     * @var int
     */
    protected $prePageDefault = 15;

    /**
     * 获取的返回的字段
     *
     * @var array
     */
    protected $getColumns;

    /**
     * 分页时返回的字段
     *
     * @var array
     */
    protected $paginateColumns;

    /**
     * 是否默认导出
     *
     * @var bool
     */
    protected $defaultExport = false;

    /**
     * 导出的名称
     *
     * @var string
     */
    protected $exportName = 'export';

    /**
     * 默认数据
     *
     * @var mixed
     */
    protected $defaultData;

    /**
     * @var string
     */
    protected $exportMemoryLimit = '40048M';

    /**
     * 指定分页总数
     *
     * @var null|int
     */
    protected $paginateCount = null;

    /**
     * 入口方法
     * 返回指定的数据
     *
     * @param Builder $query
     * @param null $data
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model[]
     */
    public function get($query, $data = null)
    {
        if ($this->isExport($data)) { // 导出
            ini_set('memory_limit', $this->getExportMemoryLimit()); // 导出时加大内存

            return $query->get(...[$this->getGetColumns()]);
        }else{
            if (!is_null($this->getPaginateCount())){ // 指定分页数量
                // 实现$query->paginate方法
                $page = \Illuminate\Pagination\Paginator::resolveCurrentPage($this->getPageName());

                $perPage = $this->getPerPage($data) ?: $query->getModel()->getPerPage();

                $results = ($total = $this->getPaginateCount())
                    ? $query->forPage($page, $perPage)->get($this->getPaginateColumns(true))
                    : $query->getModel()->newCollection();

                return app(\Illuminate\Pagination\LengthAwarePaginator::class, [
                    'items' => $results, 'total' => $total, 'perPage' => $perPage, 'currentPage' => $page, 'options' => [
                        'path' => \Illuminate\Pagination\Paginator::resolveCurrentPath(),
                        'pageName' => $this->getPageName(),
                    ]
                ]);

            }

            if (!empty($this->getPageName())){ // 指定分页名称
                return $query->paginate($this->getPerPage($data), $this->getPaginateColumns(true), $this->getPageName());
            }else if (!empty($this->getPaginateColumns())){ // 指定分页字段
                return $query->paginate($this->getPerPage($data), $this->getPaginateColumns());
            }else{ // 指定分页大小
                return $query->paginate($this->getPerPage($data));
            }
        }
    }

    /**
     * 获取分页大小
     *
     * @param null $data
     * @return array|int|string
     */
    public function getPerPage($data = null)
    {
        $pageSize = $this->getValue($this->getPrePageName(), '', $data);

        if (!empty($pageSize) && filter_var($pageSize, FILTER_VALIDATE_INT) !== false && (int) $pageSize >= 1) {
            return $pageSize;
        }

        return $this->getPrePageDefault();
    }

    /**
     * 判断是否导出
     *
     * @param null $data
     * @return array|string
     */
    public function isExport($data = null)
    {
        return $this->getValue($this->getExportName(), false, $data);
    }

    /**
     * 获取值
     *
     * @param $key
     * @param string $default
     * @param null $data
     * @return array|string
     */
    public function getValue($key, $default = '', $data = null)
    {
        if (!empty($data) && isset($data[$key])) {
            return $data[$key]?:$default;
        }else if (!empty($this->getDefaultData()) && isset($this->getDefaultData()[$key])) {
            return $this->getDefaultData()[$key]?:$default;
        }

        return request()->input($key, $default);
    }

    /**
     * @param string $prePageName
     * @return ModelPaginateExportTool
     */
    public function setPrePageName(string $prePageName): ModelPaginateExportTool
    {
        $this->prePageName = $prePageName;
        return $this;
    }

    /**
     * @return string
     */
    public function getPrePageName(): string
    {
        return $this->prePageName;
    }

    /**
     * @param int $prePageDefault
     * @return ModelPaginateExportTool
     */
    public function setPrePageDefault(int $prePageDefault): ModelPaginateExportTool
    {
        $this->prePageDefault = $prePageDefault;
        return $this;
    }

    /**
     * @return int
     */
    public function getPrePageDefault(): int
    {
        return $this->prePageDefault;
    }

    /**
     * @param array $getColumns
     * @return ModelPaginateExportTool
     */
    public function setGetColumns(array $getColumns): ModelPaginateExportTool
    {
        $this->getColumns = $getColumns;
        return $this;
    }

    /**
     * @return array
     */
    public function getGetColumns()
    {
        return $this->getColumns;
    }

    /**
     * @param array $paginateColumns
     * @return ModelPaginateExportTool
     */
    public function setPaginateColumns(array $paginateColumns): ModelPaginateExportTool
    {
        $this->paginateColumns = $paginateColumns;
        return $this;
    }

    /**
     * @param bool $defaultBool 是否返回默认值
     * @return array
     */
    public function getPaginateColumns($defaultBool = false)
    {
        return $this->paginateColumns ?: ($defaultBool ? ['*'] : $this->paginateColumns);
    }

    /**
     * @param string $pageName
     * @return ModelPaginateExportTool
     */
    public function setPageName(string $pageName): ModelPaginateExportTool
    {
        $this->pageName = $pageName;
        return $this;
    }

    /**
     * @return string
     */
    public function getPageName(): string
    {
        return $this->pageName;
    }

    /**
     * @param bool $defaultExport
     * @return ModelPaginateExportTool
     */
    public function setDefaultExport(bool $defaultExport): ModelPaginateExportTool
    {
        $this->defaultExport = $defaultExport;
        return $this;
    }

    /**
     * @return bool
     */
    public function isDefaultExport(): bool
    {
        return $this->defaultExport;
    }

    /**
     * @param string $exportName
     * @return ModelPaginateExportTool
     */
    public function setExportName(string $exportName): ModelPaginateExportTool
    {
        $this->exportName = $exportName;
        return $this;
    }

    /**
     * @return string
     */
    public function getExportName(): string
    {
        return $this->exportName;
    }

    /**
     * @param mixed $defaultData
     * @return ModelPaginateExportTool
     */
    public function setDefaultData($defaultData)
    {
        $this->defaultData = $defaultData;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getDefaultData()
    {
        return $this->defaultData;
    }

    /**
     * @param string $exportMemoryLimit
     * @return ModelPaginateExportTool
     */
    public function setExportMemoryLimit(string $exportMemoryLimit): ModelPaginateExportTool
    {
        $this->exportMemoryLimit = $exportMemoryLimit;

        return $this;
    }

    /**
     * @return string
     */
    public function getExportMemoryLimit(): string
    {
        return $this->exportMemoryLimit;
    }

    /**
     * @param null|int $paginateCount
     * @return $this
     */
    public function setPaginateCount($paginateCount)
    {
        $this->paginateCount = $paginateCount;
        return $this;
    }

    /**
     * @return null|int
     */
    public function getPaginateCount()
    {
        return $this->paginateCount;
    }
}
<?php
namespace App\Listeners;

use Illuminate\Database\Events\QueryExecuted;
/**
 * 保存执行的sql语句
 * 修改文件:app/Providers/EventServiceProvider.php
 *
 * @example  使用:

protected $listen = [
    \Illuminate\Database\Events\QueryExecuted::class => [
        \App\Listeners\SaveSqlListener::class
    ],
];


public function boot()
{
    \App\Listeners\SaveSqlListener::setCacheBool();
    \App\Listeners\SaveSqlListener::saveFile(); // 本地
    parent::boot();

    //
}
 *
 */
class SaveSqlListener
{
    /**
     * 手动开启
     *
     * @var bool
     */
    protected static $closeBool = true;
    /**
     * 是否直接输出
     *
     * @var callable[]|\Closure[]
     */
    protected static $autoSendCallback = [];

    /**
     * 对象缓存
     *
     * @var array
     */
    protected static $cache = [];

    /**
     * 是否开启对象缓存
     *
     * @var bool
     */
    protected static $cacheBool = false;

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * @return array
     */
    public static function getCache(): array
    {
        return static::$cache;
    }
    /**
     * @param bool $closeBool
     */
    public static function setCloseBool(bool $closeBool)
    {
        static::$closeBool = $closeBool;
    }
    /**
     * @param callable $autoSendCallback
     */
    public static function setAutoSendCallback(callable $autoSendCallback)
    {
        static::$autoSendCallback = [];
        static::addAutoSendCallback($autoSendCallback);
    }

    public static function addAutoSendCallback(callable $autoSendCallback)
    {
        if (!is_callable($autoSendCallback)){
            return;
        }

        static::$autoSendCallback[] = $autoSendCallback;
    }

    /**
     * 指定保存到文件
     * @param string $logPath
     */
    public static function saveFile($logPath = 'logs/sql.log')
    {
        static::addAutoSendCallback(function ($data) use($logPath){
            file_put_contents(storage_path($logPath),  str_repeat('=', 40) . PHP_EOL, FILE_APPEND);
            file_put_contents(storage_path($logPath), var_export($data, true) . PHP_EOL, FILE_APPEND);
        });
    }

    /**
     * @param bool $cacheBool
     */
    public static function setCacheBool(bool $cacheBool = true): void
    {
        self::$cacheBool = $cacheBool;
    }

    /**
     * Handle the event.
     *
     * @param  QueryExecuted  $event
     * @return void
     */
    public function handle(QueryExecuted $event)
    {
        if (config('app.env') == 'production' && self::$closeBool) { // 线上环境不记录
            return;
        }
        $data = [
            'sql' => $event->sql,
            'bindings' => $event->bindings,
            'time' => $event->time,
        ];
        if (!empty(static::$autoSendCallback)){
            foreach (static::$autoSendCallback as $item) {
                call_user_func($item, $data);
            }
        }

        if (static::$cacheBool){
            static::$cache[] = $data;
        }
    }
}
<?php
/**
 * Created by PhpStorm.
 * User: code
 * Date: 2018/10/17
 * Time: 下午5:40
 */

namespace App\Repositories\Common\Traits;


use App\Models\Model;
use App\Repositories\Common\FuncMiddleware;

trait SingleApiControllerTrait
{
    /**
     * 获取列表
     *
     * @param string $modelName
     * @param array $field
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    protected function simplePageTrait($modelName, $field = null)
    {
        $this->validatorAll([
            'total' => 'integer|min:0',
        ]);
        $total = request()->input('total');

        /** @var Model $modelClass */
        $modelClass = app($modelName);

        return $modelClass->where([])->select(...argsSaveDefault($field))->paginate($total);
    }

    /**
     * 根据id获取详情
     *
     * @param string $modelName
     * @param array $field
     * @return \Illuminate\Database\Eloquent\Model|mixed|null|static
     */
    protected function detailByIdTrait($modelName, $field = null)
    {
        $this->validatorAll([
            'id' => 'required|integer|min:1',
        ]);

        $id = request()->input('id');

        /** @var Model $modelClass */
        $modelClass = app($modelName);

        $data = $modelClass->where('id', $id)->first(...argsSaveDefault($field));

        if (emptyA($data)){ // 空数据
            $this->throwJson($this->success());
        };

        return $data;
    }

    /**
     * 根据$where执行updateOrCreate
     *
     *         $this->updateOrCreateTrait(DemoModel::class, [
     *              'staff_id' => Auth::id(),
     *          ], [
     *              'name' => 'required|string|max:20',
     *              'first_text' => 'required|string',
     *              'voice_text' => 'required|string',
     *          ]);
     *
     * @param $modelName
     * @param $where
     * @param array $rule
     * @param array $allowField
     * @return Model|bool
     */
    protected function updateOrCreateTrait($modelName, $where, $rule = [], $allowField = [])
    {
        $request = request();

        if (!$request->isMethod('POST')) {
            $this->throwJson($this->error(trans('messages.request-error')));
        }

        $this->validatorAll($rule);

        $data = $request->request->all();
        if (!empty($allowField)) {
            $data = array_intersect_key($data, array_flip($allowField));
        }

        return FuncMiddleware::instance()->call('updateOrCreateTrait', function ($data)use($modelName, $where){
            /** @var Model $modelClass */
            $modelClass = app($modelName);
            /** @var Model $modelData */
            return $modelClass->updateOrCreate($where, $data);
        }, $data);
    }

    /**
     * 根据id更新数据
     * create返回model
     * update返回bool
     *
     * @param $modelName
     * @param array $rule
     * @param array $allowField
     * @param array $createRule 创建时的规则
     * @return Model|bool
     */
    protected function updateByIdTrait($modelName, $rule = [], $allowField = [], $createRule = [])
    {
        $request = request();

        if (!$request->isMethod('POST')) {
            $this->throwJson($this->error(trans('messages.request-error')));
        }

        $this->validatorAll([
            'id' => ['sometimes', 'required', 'integer'],
        ]);
        $this->validatorAll($rule);

        $id = $request->input('id');
        $data = $request->request->all();
        if (!empty($allowField)) {
            $data = array_intersect_key($data, array_flip($allowField));
        }

        /** @var Model $modelClass */
        $modelClass = app($modelName);

        if (empty($id)) { // 创建成功后需要返回
            $this->validatorAll($createRule); // 会自动抛出

            return FuncMiddleware::instance()->call('updateByIdTrait.create', function ($data)use($modelClass, $id){
                /** @var Model $modelData */
                return $modelClass->create($data);
            }, $data);
        }else{
            $data['id'] = $id; // 补充回id
            $modelData = $modelClass->find($id);

            if (emptyA($modelData)) { // 不存在的数据
                $this->throwJson($this->error(trans('messages.request-error')));
            }

            return FuncMiddleware::instance()->call('updateByIdTrait.update', function ($data, $modelData)use($id){
                /** @var Model $modelData */
                return $modelData->where('id', $id)->update($data);
            }, $data, $modelData);
        }
    }

    /**
     * 封装上面方法
     * 用于保证创建的唯一性
     * 限制唯一条件$unqiueField
     *
     * @param string $unqiueField
     * @inheritdoc
     */
    protected function updateAtUniqueByIdTrait($modelName, $unqiueField, $rule = [], $allowField = [])
    {
        return $this->updateByIdTrait($modelName, $rule, $allowField, [
            $unqiueField => $this->uniqueRuleByModelName($modelName, $unqiueField),
        ]);
    }

    /**
     * 唯一字段的规则
     *
     * @param string $modelName
     * @param string $unqiueField
     * @return string
     */
    protected function uniqueRuleByModelName($modelName, $unqiueField)
    {
        /** @var Model $modelClass */
        $modelClass = app($modelName);
        return 'unique:' . join('.', array_filter([$modelClass->getConnectionName(), $modelClass->getTable()])) . ',' . $unqiueField;
    }

    /**
     * 根据id删除
     *
     * @param $modelName
     * @return bool|int|mixed|null
     * @throws \Exception
     */
    protected function deleteByIdTrait($modelName)
    {
        $this->validatorAll([
            'id' => 'integer|min:0',
        ]);
        $id = request()->input('id');

        /** @var Model $modelClass */
        $modelClass = app($modelName);

        return $modelClass->where('id', $id)->delete();
    }
}
<?php
/**
 * User: aozhuochao
 * Date: 2021/1/22
 */

namespace App\Library\Traits;

/**
 *  fastcgi_finish_request
 * 输出response后再执行的代码
 * 
 * @example 
\Illuminate\Support\Facades\Event::listen('http_end', function ($request, $response) { 
    $a = 1; 
});
 * 
 */
trait KernelTerminateHttpEndEventsTrait
{


    public function terminate($request, $response)
    {
        event('http_end', [$request, $response]);

        parent::terminate($request, $response);
    }

}
<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;


    /**
     * 验证通过就返回验证的数据
     * 没通过直接报错
     *
     * @param $rules
     * @param array $customAttributes
     * @param array $messages
     * @return array
     */
    public function getValidationData($rules, $customAttributes = [], $messages = [])
    {
        return $this->validate(request(), $rules, $messages, $customAttributes);
    }

    /**
     * @param string $message
     * @param int $code
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondError($message = '发生错误', $code = 400)
    {
        return $this->respondWithJson(null, $code, $message);
    }

    /**
     * 返回前端的结构
     * @param array $data
     * @param bool $status
     * @param int $code
     * @param string $message
     * @param int $error_code
     * @return \Illuminate\Http\JsonResponse
     */
    public function respondWithJson($data = null, $code = 200, $message = "success", $error_code = 200)
    {

        $response_data = [
            'code' => $code,
            'message' => $message
        ];

        if (!is_null($data)) {
            $response_data['data'] = $data;
        }

        return response()->json($response_data, $error_code);
    }
}
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Validation\ValidationException;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param \Exception $exception
     * @return void
     *
     * @throws \Exception
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Exception $exception
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Exception
     */
    public function render($request, Exception $exception)
    {
        return parent::render($request, $exception);
    }

   /**
     * 定义验证错误时返回的数据结构
     * 
     * @param ValidationException $e
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
     */
    protected function convertValidationExceptionToResponse(ValidationException $e, $request)
    {
        if ($request->expectsJson()) {
            $data = $e->validator->getMessageBag();
            $msg = collect($data)->first();
            if (is_array($msg)) {
                $msg = $msg[0];
            }
            return response()->json(['message' => $msg, "code" => 201]);
        }
        return parent::convertValidationExceptionToResponse($e, $request); // TODO: Change the autogenerated stub
    }
}
<?php
/**
 * Created by PhpStorm.
 * User: code
 * Date: 2018/3/19
 * Time: 下午4:55
 */

namespace App\Models;


/**
 * Class Model
 *
 * @package App\Models
 * @since \Illuminate\Database\Eloquent\Builder
 */
class Model extends \Illuminate\Database\Eloquent\Model
{
    use \App\Libs\Traits\DocModelTrait;
    use \App\Models\Traits\ModelExtendTrait;

    /**
     * 可用来取消更新created_at和updated_at
     *
     * @var bool
     */
    public $timestamps = true;

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
    }


}
<?php

/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/

$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
|
| Next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. The kernels serve the
| incoming requests to this application from both the web and CLI.
|
*/

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

// 根据.env使用不同.env.*后缀的环境变量
$env = $app->detectEnvironment(function () use ($app) { // 配置示例: suffix=local
    $environmentPath = $app->environmentPath();//.env所在目录

    // putenv("APP_ENV=$setEnv");//写入env     //getenv('APP_ENV');//获取env
    $setEnv = trim(file_get_contents($environmentPath . '/.env'));//获取.env文件内容

    $str_encoding = mb_convert_encoding($setEnv, 'UTF-8', 'UTF-8,GBK,GB2312,BIG5');//转换字符集(编码)
    $arr = explode("\n", $str_encoding);//转换成数组
    $new_arr = array();
    //去除值中的空格
    foreach ($arr as &$row) {
        $row_arr = explode("=", trim($row));//转换成数组
        $new_arr[$row_arr[0]??''] = trim($row_arr[1]??'');
    }

    unset($row);

    $tailAffix = $setEnv;

    if (array_key_exists("suffix", $new_arr)) {
        $tailAffix = $new_arr["suffix"];
    }


    if ( // local环境可以自定义环境
        !empty($tailAffix) && $tailAffix === 'local' &&
        (
            (!empty($temp = $_SERVER['HTTP_PROJECT_ENV']) && file_exists($environmentPath . '/.env.' . $_SERVER['HTTP_PROJECT_ENV'])) || // http
            !empty($temp = env('PROJECT_ENV')) // 命令行
        )

    ) {
        $app->loadEnvironmentFrom('.env.' . $temp);
        return;
    }

    if (file_exists($environmentPath)) {
        $app->loadEnvironmentFrom('.env.' . $tailAffix);
    }
});

/*
|--------------------------------------------------------------------------
| Return The Application
|--------------------------------------------------------------------------
|
| This script returns the application instance. The instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/

return $app;
<?php

namespace App\Libs;

use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger as Monolog;
use Monolog\Processor\PsrLogMessageProcessor;

/**
 * 支持动态日志名
 *
 * @method static \Psr\Log\LoggerInterface driverPath($morePath, $driver = null)
 */
class SysLogManager extends \Illuminate\Log\LogManager
{
    /**
     * Get a log driver instance.
     * \App\Libs\SysLogManager::app()->driverPath(class_basename($this), 'command')->info($message);
     *
     * @param  string  $morePath
     * @param  string|null  $driver
     * @return \Psr\Log\LoggerInterface
     */
    public function driverPath($morePath, $driver = null)
    {
        $name = $this->parseDriver($driver);
        $config = $this->configurationFor($name);
        if (empty($config['path'])) {
            $config['path'] = storage_path('logs/'.$driver.'.log');
        }
        $config['path'] .= '/' . $morePath . '.log';

        return $this->get($this->parseDriver($driver), $config);
    }

    /**
     * @return $this
     */
    public static function app()
    {
        if (!app()->has('sysLog')) {
            app()->singleton('sysLog', fn($app) => new static($app));
        }

        return app('sysLog');
    }
}
<?php

namespace App\Console;

abstract class BaseProCommand extends BaseCommand
{


    /**
     * 0=成功
     *
     * @return int
     */
    public function handle()
    {
        try{
            return $this->handlePro()??0;
        }catch (\Throwable $throwable){
            $arr = get_exception_laravel_array($throwable);
            if (is_local()) {
                var_dump($arr);
            }

            $this->errorCommand($arr);
        }

        return 1;
    }

    protected abstract function handlePro();

}
<?php

namespace App\Http\Middleware;

/**
 * @see fastcgi_finish_request
 */
class TerminateMiddleware
{
    public function handle(\Illuminate\Http\Request $request, \Closure $next)
    {
        return $next($request);
    }

    /**
     * @see \Illuminate\Foundation\Http\Kernel::terminate
     * @param \Illuminate\Http\Request $request
     * @return void
     */
    public function terminate($request, $response)
    {

        try{

            event('terminate');
        }catch (\Throwable $throwable){
            log_push_daily($throwable, ['$request' => $request->all()]);
        }

    }

}
<?php

namespace App\Providers;

/**
 * 生成.phpstorm.meta.php文件,方便trans()
 */
class LocalLangPhpStormServiceProvider extends \Illuminate\Support\ServiceProvider
{

    public function boot()
    {
        if (!app()->environment('local')) {
            return;
        }

        $metaFilePath = lang_path('/.phpstorm.meta.php');
        $fileUpdateTime = 0;
        if (file_exists($metaFilePath)) {
            $fileUpdateTime = filemtime($metaFilePath);
        }
        /*
         *
    registerArgumentsSet('langs', 'admin.created_at', 'admin.updated_at');
    expectedArguments(\trans(), 0, argumentsSet('langs'));
         * */

        $locale = config('app.locale');
        $bool = false;
        foreach (\glob(lang_path() . '/' . $locale . '/*.php') as $item) {
            if (filemtime($item) > $fileUpdateTime) {
                $bool = true;
                break;
            }
        }
        foreach (\glob(lang_path() . '/' . $locale . '/*/*.php') as $item) {
            if (filemtime($item) > $fileUpdateTime) {
                $bool = true;
                break;
            }
        }
        
        if (!$bool) {
            return;
        }

        $registerArgumentsSetList = [];
        $adminArr = [];

        foreach (\glob(lang_path() . '/' . $locale . '/*.php') as $item) {

            $key = preg_replace('/\.php/', '', basename($item));
            $arr = include_once $item;
            if (!is_array($arr)) {
                continue;
            }
            foreach ($arr as $arrKey => $arrItem) {
                $registerArgumentsSetList[] = "'" . $key . '.' . $arrKey . "'";

                if ($key === 'admin') {
                    $adminArr[] = "'" . $arrKey . "'";
                }
            }
        }
        $registerArgumentsSetList = join(',', $registerArgumentsSetList);
        $adminArr = join(',', $adminArr);

        file_put_contents($metaFilePath, <<<PHP
<?php
// @formatter:off

namespace PHPSTORM_META {
    registerArgumentsSet('langs', {$registerArgumentsSetList});
    expectedArguments(\\trans(), 0, argumentsSet('langs'));
    
    registerArgumentsSet('langs_admin', {$adminArr});
    expectedArguments(\\trans_admin(), 0, argumentsSet('langs_admin'));

}
PHP

);
    }
}
<?php

namespace App\Libs;

/**
 * 支持自动空格
 */
class SysTranslator extends \Illuminate\Translation\Translator
{
    public function get($key, array $replace = [], $locale = null, $fallback = true)
    {
        $newKey = preg_replace(['/__join$/', '/__join_both$/'], ['', ''], $key);

        $result = parent::get($newKey, $replace, $locale, $fallback);

        if (str_ends_with($key, '__join')) {
            $result .= ' ';
        }else if (str_ends_with($key, '__join_both')) {
            $result = ' ' . $result . ' ';
        }

        return $result;
    }


}