├── README.md ├── composer.json ├── config └── laravel-quick.php ├── resources └── lang │ └── zh-CN │ ├── admin.php │ ├── auth.php │ ├── select2.php │ └── validation.php └── src ├── Console ├── CreateRepositoryCommand.php ├── CreateServiceCommand.php ├── CreateTraitCommand.php └── stubs │ ├── repository.stub │ ├── service.stub │ └── trait.stub ├── Exceptions ├── Api │ ├── ApiNotFoundException.php │ ├── ApiRequestException.php │ ├── ApiSystemException.php │ └── ApiUnAuthException.php └── ApiException.php ├── Facades └── CacheClient.php ├── Helpers └── helper.php ├── LaravelQuickServiceProvider.php ├── Repositories └── BaseRepository.php ├── Services ├── BaseService.php └── CacheService.php └── Traits ├── AttributeStatusTrait.php └── JsonResponseTrait.php /README.md: -------------------------------------------------------------------------------- 1 | # laravel-quick 2 | 3 | **laravel-quick** 封装了一些我们开发中常见的工具,使开发变得更高效 4 | 5 | ## 安装 6 | - `composer require yxx/laravel-quick` 7 | - 生成翻译好的中文包命令 8 | 9 | **linux 和 mac** `php artisan vendor:publish--provider="Yxx\\LaravelQuick\\LaravelQuickServiceProvider"` 10 | **windows** `php artisan vendor:publish --provider="Yxx\LaravelQuick\LaravelQuickServiceProvider"` 11 | ## 怎么使用 12 | ```$xslt 13 | // api 返回状态码 14 | 15 | // 异常使用例子 16 | use Yxx\LaravelQuick\Exceptions\Api\ApiNotFoundException; 17 | // 请求参数错误 18 | throw new ApiRequestException(); 19 | // 404 未找到 20 | throw new ApiNotFoundException(); 21 | // 系统错误 22 | throw new ApiSystemException() 23 | // 未授权 24 | throw new ApiUnAuthException() 25 | // 返回 26 | 27 | //自定义错误继承Yxx\LaravelQuick\Exceptions自己参照对应代码自定义 28 | 29 | // api接口使用 30 | use Yxx\LaravelQuick\Traits\JsonResponseTrait 31 | 32 | // 成功 33 | return $this->success("消息",['name'=>"张三"]); 34 | // 失败 35 | return $this->error("错误"); 36 | // 自定义 37 | return $this->apiResponse(Response::HTTP_BAD_GATEWAY,"502错误"); 38 | 39 | // 缓存的使用(封装了redis的一些方法) 40 | use Yxx\LaravelQuick\Facades\CacheClient; 41 | 42 | CacheClient::hSet("test","1","张三"); 43 | CacheClient::hGet("test","1"); 44 | CacheClient::lPush("test","1"); 45 | 46 | 具体参考Yxx\LaravelQuick\Services\CacheService里面的方法.... 47 | ``` 48 | 49 | ## artisan 命令 50 | - 创建 Trait `php artisan quick:create-trait test` 51 | - 创建 Service `php artisan quick:create-service Test/TestService` 52 | - 创建 Repository `php artisan quick:create-repository Test` 53 | 54 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yxx/laravel-quick", 3 | "keywords": ["laravel","php","tool","api","scaffold"], 4 | "description": "agile development", 5 | "type": "library", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "youxingxiang", 10 | "email": "1365831278@qq.com" 11 | } 12 | ], 13 | "require": { 14 | "php": ">=7.1.0", 15 | "laravel/framework": "~5.5|~6.0|~7.0|~8.0" 16 | }, 17 | "autoload": { 18 | "psr-4": { 19 | "Yxx\\LaravelQuick\\": "src/" 20 | }, 21 | "files": [ 22 | "src/Helpers/helper.php" 23 | ] 24 | }, 25 | "extra": { 26 | "laravel": { 27 | "providers": [ 28 | "Yxx\\LaravelQuick\\LaravelQuickServiceProvider" 29 | ], 30 | "aliases": { 31 | "CacheClient": "Yxx\\LaravelQuick\\Facades\\CacheClient::class" 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /config/laravel-quick.php: -------------------------------------------------------------------------------- 1 | env('REDIS_KEY_EXPIRE', 3600 * 24 * 30), 10 | ]; 11 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/admin.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'header' => '代码生成器', 6 | 'choose' => '选择已有数据表', 7 | 'table' => '表名', 8 | 'model' => '模型', 9 | 'controller' => '控制器', 10 | 'repository' => '数据仓库', 11 | 'add_field' => '添加字段', 12 | 'pk' => '主键', 13 | 'soft_delete' => '软删除', 14 | 'create_migration' => '创建表迁移文件', 15 | 'create_model' => '创建模型', 16 | 'create_repository' => '创建数据仓库', 17 | 'create_controller' => '创建控制器', 18 | 'run_migrate' => '创建数据表', 19 | 'create_lang' => '创建翻译文件', 20 | 'field' => '字段', 21 | 'translation' => '翻译', 22 | 'comment' => '注释', 23 | 'default' => '默认值', 24 | 'field_name' => '字段名', 25 | 'type' => '类型', 26 | 'nullable' => '允许空值', 27 | 'key' => '索引', 28 | ], 29 | 'client' => [ 30 | 'delete_confirm' => '确认删除?', 31 | 'confirm' => '确认', 32 | 'cancel' => '取消', 33 | 'refresh_succeeded' => '刷新成功 !', 34 | 'close' => '关闭', 35 | 'selected_options' => '已选中:num个选项', 36 | 'exceed_max_item' => '已超出最大可选数量', 37 | 38 | '500' => '系统繁忙,请稍后再试!', 39 | '403' => '对不起,您没有权限访问,请与管理员联系。', 40 | '401' => '请登录!', 41 | '419' => '对不起,当前页面已失效,请刷新浏览器。', 42 | ], 43 | 'home' => '主页', 44 | 'online' => '在线', 45 | 'login' => '登录', 46 | 'logout' => '登出', 47 | 'setting' => '设置', 48 | 'name' => '名称', 49 | 'username' => '用户名', 50 | 'old_password' => '旧密码', 51 | 'password' => '密码', 52 | 'password_confirmation' => '确认密码', 53 | 'old_password_error' => '请输入正确的旧密码', 54 | 'remember_me' => '记住我', 55 | 'user_setting' => '用户设置', 56 | 'avatar' => '头像', 57 | 'list' => '列表', 58 | 'new' => '新增', 59 | 'create' => '创建', 60 | 'delete' => '删除', 61 | 'remove' => '移除', 62 | 'edit' => '编辑', 63 | 'quick_edit' => '快捷编辑', 64 | 'continue_editing' => '继续编辑', 65 | 'continue_creating' => '继续创建', 66 | 'view' => '查看', 67 | 'detail' => '详细', 68 | 'browse' => '浏览', 69 | 'reset' => '重置', 70 | 'export' => '导出', 71 | 'batch_delete' => '批量删除', 72 | 'save' => '保存', 73 | 'refresh' => '刷新', 74 | 'order' => '排序', 75 | 'expand' => '展开', 76 | 'collapse' => '收起', 77 | 'filter' => '筛选', 78 | 'search' => '搜索', 79 | 'close' => '关闭', 80 | 'show' => '显示', 81 | 'entries' => '条', 82 | 'captcha' => '验证码', 83 | 'action' => '操作', 84 | 'title' => '标题', 85 | 'description' => '简介', 86 | 'back' => '返回', 87 | 'back_to_list' => '返回列表', 88 | 'submit' => '提交', 89 | 'menu' => '菜单', 90 | 'input' => '输入', 91 | 'succeeded' => '成功', 92 | 'failed' => '失败', 93 | 'delete_confirm' => '确认删除?', 94 | 'delete_succeeded' => '删除成功 !', 95 | 'delete_failed' => '删除失败 !', 96 | 'update_succeeded' => '更新成功 !', 97 | 'update_failed' => '更新失败 !', 98 | 'save_succeeded' => '保存成功 !', 99 | 'save_failed' => '保存失败 !', 100 | 'refresh_succeeded' => '刷新成功 !', 101 | 'login_successful' => '登录成功 !', 102 | 'choose' => '选择', 103 | 'choose_file' => '选择文件', 104 | 'choose_image' => '选择图片', 105 | 'more' => '更多', 106 | 'deny' => '无权访问', 107 | 'administrator' => '管理员', 108 | 'roles' => '角色', 109 | 'permissions' => '权限', 110 | 'slug' => '标识', 111 | 'created_at' => '创建时间', 112 | 'updated_at' => '更新时间', 113 | 'alert' => '注意', 114 | 'parent_id' => '父级', 115 | 'icon' => '图标', 116 | 'uri' => '路径', 117 | 'operation_log' => '操作日志', 118 | 'parent_select_error' => '父级选择错误', 119 | 'default' => '默认', 120 | 'table' => '表格', 121 | 'no_data' => '暂无数据', 122 | 'routes' => '路由', 123 | 'alias' => '别名', 124 | 'route_action' => '处理器', 125 | 'middleware' => '中间件', 126 | 'import' => '导入', 127 | 'is_not_import' => '未导入', 128 | 'selected_options' => '已选中:num个选项', 129 | 'method' => '方法', 130 | 'user' => '用户', 131 | 'pagination' => [ 132 | 'range' => '从 :first 到 :last ,总共 :total 条', 133 | ], 134 | 'role' => '角色', 135 | 'permission' => '权限', 136 | 'route' => '路由', 137 | 'confirm' => '确认', 138 | 'cancel' => '取消', 139 | 'selectall' => '全选', 140 | 'http' => [ 141 | 'method' => 'HTTP方法', 142 | 'path' => 'HTTP路径', 143 | ], 144 | 'all_methods_if_empty' => '为空默认为所有方法', 145 | 'all' => '全部', 146 | 'current_page' => '当前页', 147 | 'selected_rows' => '选择的行', 148 | 'upload' => '上传', 149 | 'new_folder' => '新建文件夹', 150 | 'time' => '时间', 151 | 'size' => '大小', 152 | 'between_start' => '起始', 153 | 'between_end' => '结束', 154 | 'next_page' => '下一页', 155 | 'prev_page' => '上一页', 156 | 'next_step' => '下一步', 157 | 'prev_step' => '上一步', 158 | 'done' => '完成', 159 | 'listbox' => [ 160 | 'text_total' => '总共 {0} 项', 161 | 'text_empty' => '空列表', 162 | 'filtered' => '{0} / {1}', 163 | 'filter_clear' => '显示全部', 164 | 'filter_placeholder' => '过滤', 165 | ], 166 | 'responsive' => [ 167 | 'display_all' => '显示全部', 168 | 'display' => '字段', 169 | 'focus' => '聚焦', 170 | ], 171 | 'uploader' => [ 172 | 'add_new_media' => '添加文件', 173 | 'drag_file' => '或将文件拖到这里', 174 | 'max_file_limit' => 'The :attribute may not be greater than :max.', 175 | 'exceed_size' => '文件大小超出', 176 | 'interrupt' => '上传暂停', 177 | 'upload_failed' => '上传失败,请重试', 178 | 'selected_files' => '选中:num个文件,共:size。', 179 | 'selected_has_failed' => '已成功上传:success个文件,:fail个文件上传失败,重新上传失败文件或忽略', 180 | 'selected_success' => '共:num个(:size),已上传:success个。', 181 | 'dot' => ',', 182 | 'failed_num' => '失败:fail个。', 183 | 'pause_upload' => '暂停上传', 184 | 'go_on_upload' => '继续上传', 185 | 'start_upload' => '开始上传', 186 | 'upload_success_message' => '已成功上传:success个文件', 187 | 'go_on_add' => '继续添加', 188 | 'Q_TYPE_DENIED' => '对不起,不允许上传此类型文件', 189 | 'Q_EXCEED_NUM_LIMIT' => '对不起,已超出文件上传数量限制,最多只能上传:num个文件', 190 | 'F_EXCEED_SIZE' => '对不起,当前选择的文件过大', 191 | 'Q_EXCEED_SIZE_LIMIT' => '对不起,已超出文件大小限制', 192 | 'F_DUPLICATE' => '文件重复', 193 | 'confirm_delete_file' => '您确定要删除这个文件吗?', 194 | ], 195 | 'import_extension_confirm' => '确认导入拓展?', 196 | 'quick_create' => '快速创建', 197 | 'grid_items_selected' => '已选择 {n} 项', 198 | 'nothing_updated' => '没有任何数据被更改', 199 | 'welcome_back' => '欢迎回来,请登录您的账号。', 200 | 'documentation' => '文档', 201 | 'demo' => '示例', 202 | 'extensions' => '扩展', 203 | 'validation' => [ 204 | 'match' => '与 :attribute 不匹配。', 205 | 'minlength' => ':attribute 字符长度不能少于 :min。', 206 | 'maxlength' => ':attribute 字符长度不能超出 :max。', 207 | ], 208 | 'menu_titles' => [ 209 | 'index' => '主页', 210 | 'admin' => '系统', 211 | 'users' => '管理员', 212 | 'roles' => '角色', 213 | 'permission' => '权限', 214 | 'menu' => '菜单', 215 | 'operation_log' => '操作日志', 216 | 'helpers' => '开发工具', 217 | 'extensions' => '扩展', 218 | 'scaffold' => '代码生成器', 219 | 'icons' => '图标', 220 | ], 221 | ]; 222 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/auth.php: -------------------------------------------------------------------------------- 1 | '用户名或密码错误。', 17 | 'throttle' => '您的尝试登录次数过多,请 :seconds 秒后再试。', 18 | 'The token has been blacklisted' => '令牌已列入黑名单', 19 | 'Token has expired' => 'Token 已过期', 20 | 'Token could not be parsed from the request.' => '无法从请求中解析令牌。', 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/select2.php: -------------------------------------------------------------------------------- 1 | '无法载入结果', 5 | 'input_too_long' => '请删除:num个字符', 6 | 'input_too_short' => '请输入至少:num个字符', 7 | 'loading_more' => '载入更多结果…', 8 | 'maximum_selected' => '最多只能选择:num个项目', 9 | 'no_results' => '未找到结果', 10 | 'searching' => '搜索中…', 11 | ]; 12 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/validation.php: -------------------------------------------------------------------------------- 1 | ':attribute 必须接受。', 16 | 'active_url' => ':attribute 不是一个有效的网址。', 17 | 'after' => ':attribute 必须要晚于 :date。', 18 | 'after_or_equal' => ':attribute 必须要等于 :date 或更晚。', 19 | 'alpha' => ':attribute 只能由字母组成。', 20 | 'alpha_dash' => ':attribute 只能由字母、数字和斜杠组成。', 21 | 'alpha_num' => ':attribute 只能由字母和数字组成。', 22 | 'array' => ':attribute 必须是一个数组。', 23 | 'before' => ':attribute 必须要早于 :date。', 24 | 'before_or_equal' => ':attribute 必须要等于 :date 或更早。', 25 | 'between' => [ 26 | 'numeric' => ':attribute 必须介于 :min - :max 之间。', 27 | 'file' => ':attribute 必须介于 :min - :max KB 之间。', 28 | 'string' => ':attribute 必须介于 :min - :max 个字符之间。', 29 | 'array' => ':attribute 必须只有 :min - :max 个单元。', 30 | ], 31 | 'boolean' => ':attribute 必须为布尔值。', 32 | 'confirmed' => ':attribute 两次输入不一致。', 33 | 'date' => ':attribute 不是一个有效的日期。', 34 | 'date_format' => ':attribute 的格式必须为 :format。', 35 | 'different' => ':attribute 和 :other 必须不同。', 36 | 'digits' => ':attribute 必须是 :digits 位的数字。', 37 | 'digits_between' => ':attribute 必须是介于 :min 和 :max 位的数字。', 38 | 'dimensions' => ':attribute 图片尺寸不正确。', 39 | 'distinct' => ':attribute 已经存在。', 40 | 'email' => ':attribute 不是一个合法的邮箱。', 41 | 'exists' => ':attribute 不存在。', 42 | 'file' => ':attribute 必须是文件。', 43 | 'filled' => ':attribute 不能为空。', 44 | 'gt' => [ 45 | 'numeric' => ':attribute 必须大于 :value。', 46 | 'file' => ':attribute 必须大于 :value KB。', 47 | 'string' => ':attribute 必须多于 :value 个字符。', 48 | 'array' => ':attribute 必须多于 :value 个元素。', 49 | ], 50 | 'gte' => [ 51 | 'numeric' => ':attribute 必须大于或等于 :value。', 52 | 'file' => ':attribute 必须大于或等于 :value KB。', 53 | 'string' => ':attribute 必须多于或等于 :value 个字符。', 54 | 'array' => ':attribute 必须多于或等于 :value 个元素。', 55 | ], 56 | 'image' => ':attribute 必须是图片。', 57 | 'in' => '已选的属性 :attribute 非法。', 58 | 'in_array' => ':attribute 没有在 :other 中。', 59 | 'integer' => ':attribute 必须是整数。', 60 | 'ip' => ':attribute 必须是有效的 IP 地址。', 61 | 'ipv4' => ':attribute 必须是有效的 IPv4 地址。', 62 | 'ipv6' => ':attribute 必须是有效的 IPv6 地址。', 63 | 'json' => ':attribute 必须是正确的 JSON 格式。', 64 | 'lt' => [ 65 | 'numeric' => ':attribute 必须小于 :value。', 66 | 'file' => ':attribute 必须小于 :value KB。', 67 | 'string' => ':attribute 必须少于 :value 个字符。', 68 | 'array' => ':attribute 必须少于 :value 个元素。', 69 | ], 70 | 'lte' => [ 71 | 'numeric' => ':attribute 必须小于或等于 :value。', 72 | 'file' => ':attribute 必须小于或等于 :value KB。', 73 | 'string' => ':attribute 必须少于或等于 :value 个字符。', 74 | 'array' => ':attribute 必须少于或等于 :value 个元素。', 75 | ], 76 | 'max' => [ 77 | 'numeric' => ':attribute 不能大于 :max。', 78 | 'file' => ':attribute 不能大于 :max KB。', 79 | 'string' => ':attribute 不能大于 :max 个字符。', 80 | 'array' => ':attribute 最多允许 :max 个。', 81 | ], 82 | 'mimes' => ':attribute 必须是一个 :values 类型的文件。', 83 | 'mimetypes' => ':attribute 必须是一个 :values 类型的文件。', 84 | 'min' => [ 85 | 'numeric' => ':attribute 必须大于等于 :min。', 86 | 'file' => ':attribute 大小不能小于 :min KB。', 87 | 'string' => ':attribute 至少 :min 个字符。', 88 | 'array' => ':attribute 至少要 :min 个。', 89 | ], 90 | 'not_in' => '已选的属性 :attribute 非法。', 91 | 'not_regex' => ':attribute 的格式错误。', 92 | 'numeric' => ':attribute 必须是一个数字。', 93 | 'present' => ':attribute 必须存在。', 94 | 'regex' => ':attribute 格式不正确。', 95 | 'required' => ':attribute 不能为空。', 96 | 'required_if' => '当 :other 为 :value 时 :attribute 不能为空。', 97 | 'required_unless' => '当 :other 不为 :value 时 :attribute 不能为空。', 98 | 'required_with' => '当 :values 存在时 :attribute 不能为空。', 99 | 'required_with_all' => '当 :values 存在时 :attribute 不能为空。', 100 | 'required_without' => '当 :values 不存在时 :attribute 不能为空。', 101 | 'required_without_all' => '当 :values 都不存在时 :attribute 不能为空。', 102 | 'same' => ':attribute 和 :other 必须相同。', 103 | 'size' => [ 104 | 'numeric' => ':attribute 大小必须为 :size。', 105 | 'file' => ':attribute 大小必须为 :size KB。', 106 | 'string' => ':attribute 必须是 :size 个字符。', 107 | 'array' => ':attribute 必须为 :size 个。', 108 | ], 109 | 'string' => ':attribute 必须是一个字符串。', 110 | 'timezone' => ':attribute 必须是一个合法的时区值。', 111 | 'unique' => ':attribute 已经存在。', 112 | 'uploaded' => ':attribute 上传失败。', 113 | 'url' => ':attribute 格式不正确。', 114 | 'phone' => ':attribute 格式不正确。', 115 | 116 | /* 117 | |-------------------------------------------------------------------------- 118 | | Custom Validation Language Lines 119 | |-------------------------------------------------------------------------- 120 | | 121 | | Here you may specify custom validation messages for attributes using the 122 | | convention 'attribute.rule' to name the lines. This makes it quick to 123 | | specify a specific custom language line for a given attribute rule. 124 | | 125 | */ 126 | 127 | 'custom' => [ 128 | 'attribute-name' => [ 129 | 'rule-name' => 'custom-message', 130 | ], 131 | ], 132 | 133 | /* 134 | |-------------------------------------------------------------------------- 135 | | Custom Validation Attributes 136 | |-------------------------------------------------------------------------- 137 | | 138 | | The following language lines are used to swap attribute place-holders 139 | | with something more reader friendly such as E-Mail Address instead 140 | | of 'email'. This simply helps us make messages a little cleaner. 141 | | 142 | */ 143 | 144 | 'attributes' => [ 145 | 'name' => '名称', 146 | 'username' => '用户名', 147 | 'email' => '邮箱', 148 | 'first_name' => '名', 149 | 'last_name' => '姓', 150 | 'password' => '密码', 151 | 'password_confirmation' => '确认密码', 152 | 'city' => '城市', 153 | 'country' => '国家', 154 | 'address' => '地址', 155 | 'phone' => '电话', 156 | 'mobile' => '手机', 157 | 'age' => '年龄', 158 | 'sex' => '性别', 159 | 'gender' => '性别', 160 | 'day' => '天', 161 | 'month' => '月', 162 | 'year' => '年', 163 | 'hour' => '时', 164 | 'minute' => '分', 165 | 'second' => '秒', 166 | 'title' => '标题', 167 | 'content' => '内容', 168 | 'description' => '描述', 169 | 'excerpt' => '摘要', 170 | 'date' => '日期', 171 | 'time' => '时间', 172 | 'available' => '可用的', 173 | 'size' => '大小', 174 | 175 | 'channel' => '支付渠道', 176 | 'pay_trade_no' => '付款交易流水号', 177 | 'merchant_id' => '商户ID', 178 | 'code_sn' => '付款码编号', 179 | 'merchant_account_name' => '收款账号', 180 | 'order_no' => '平台订单号', 181 | ], 182 | ]; 183 | -------------------------------------------------------------------------------- /src/Console/CreateRepositoryCommand.php: -------------------------------------------------------------------------------- 1 | noFound($this->getMessage()); 19 | return parent::render(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Exceptions/Api/ApiRequestException.php: -------------------------------------------------------------------------------- 1 | requestError($this->getMessage()); 19 | return parent::render(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Exceptions/Api/ApiSystemException.php: -------------------------------------------------------------------------------- 1 | sysError($this->getMessage()); 18 | return parent::render(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Exceptions/Api/ApiUnAuthException.php: -------------------------------------------------------------------------------- 1 | unauthorized($this->getMessage()); 18 | return parent::render(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Exceptions/ApiException.php: -------------------------------------------------------------------------------- 1 | errorData = $data; 30 | } 31 | 32 | public function noFound($message = '') 33 | { 34 | $this->message = $message ?: '没有找到对象'; 35 | $this->code = self::NO_FOUND_ERROR; 36 | return $this; 37 | } 38 | 39 | public function unauthorized($message = '') 40 | { 41 | $this->message = $message ?: '验证失败,请先登录'; 42 | $this->code = self::AUTH_ERROR; 43 | return $this; 44 | } 45 | 46 | public function requestError($message = '') 47 | { 48 | $this->message = $message ?: '参数错误'; 49 | $this->code = self::BAD_REQUEST; 50 | return $this; 51 | } 52 | 53 | public function forbidden() 54 | { 55 | $this->message = '权限不足'; 56 | $this->code = self::PERMISSION_ERROR; 57 | return $this; 58 | } 59 | 60 | public function dbError() 61 | { 62 | $this->message = '数据库错误'; 63 | $this->code = self::DB_ERROR; 64 | return $this; 65 | } 66 | 67 | public function sysError($message = '') 68 | { 69 | $this->message = $message ?: '系统错误'; 70 | $this->code = self::SYS_ERROR; 71 | return $this; 72 | } 73 | 74 | public function render() 75 | { 76 | if (request()->pjax()) { 77 | $error = new MessageBag([ 78 | 'title' => '错误', 79 | 'message' => $this->getMessage(), 80 | ]); 81 | return back()->withInput()->with(compact('error')); 82 | } else { 83 | if (request()->input('_editable')) { 84 | return $this->apiResponse($this->getCode(), $this->getMessage(), $this->errorData, [ 85 | 'status' => false, 86 | 'errors' => [$this->getMessage()], 87 | ]); 88 | } else { 89 | return $this->apiResponse($this->getCode(), $this->getMessage(), $this->errorData); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Facades/CacheClient.php: -------------------------------------------------------------------------------- 1 | url($url); 10 | } 11 | 12 | return $url; 13 | } 14 | } 15 | if (!function_exists('hash_generate')) { 16 | function hash_generate($length = 6) 17 | { 18 | $characters = str_repeat('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', $length); 19 | 20 | return substr(str_shuffle($characters), 0, $length); 21 | } 22 | } 23 | 24 | if (!function_exists('fmt')) { 25 | function fmt($format, ...$args) 26 | { 27 | if (count($args) > 0) { 28 | $format = preg_replace("/\{[^\{]+\}/", '%s', $format); 29 | return sprintf($format, ...$args); 30 | } else { 31 | return $format; 32 | } 33 | } 34 | } 35 | 36 | function mkdirs($dir, $mode = 0777) 37 | { 38 | if (is_dir($dir) || mkdir($dir, $mode)) { 39 | return true; 40 | } 41 | if (!mkdirs(dirname($dir), $mode)) { 42 | return false; 43 | } 44 | return mkdir($dir, $mode); 45 | } 46 | -------------------------------------------------------------------------------- /src/LaravelQuickServiceProvider.php: -------------------------------------------------------------------------------- 1 | registerServices(); 34 | $this->commands($this->commands); 35 | } 36 | 37 | 38 | public function boot() 39 | { 40 | $this->registerPublishing(); 41 | } 42 | 43 | protected function registerServices() 44 | { 45 | $this->app->singleton('quick.cache.service', CacheService::class); 46 | } 47 | 48 | protected function registerPublishing() 49 | { 50 | if ($this->app->runningInConsole()) { 51 | $this->publishes([__DIR__ . '/../config' => config_path()]); 52 | $this->publishes([__DIR__ . '/../resources/lang' => resource_path('lang')]); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Repositories/BaseRepository.php: -------------------------------------------------------------------------------- 1 | setDefaultCacheTime(config('laravel-quick.redis_key_expire')); 27 | } 28 | 29 | /** 30 | * @param $key 31 | * @param $field 32 | * @param $increment 33 | * @param null $ttl 34 | */ 35 | public function hIncrBy($key, $field, $increment, $ttl = NULL) 36 | { 37 | RedisClient::hIncrBy(Cache::getPrefix() . $key, $field, $increment); 38 | if ($ttl) { 39 | $seconds = $this->getSeconds($ttl); 40 | $this->redisExpire($key, $seconds); 41 | } 42 | } 43 | 44 | /** 45 | * @param $sKey 46 | * @param $field 47 | * 48 | * @return array|mixed|string 49 | */ 50 | public function hGet($sKey, $field) 51 | { 52 | $sData = RedisClient::hGet(Cache::getPrefix() . $sKey, $field); 53 | if ($sData) { 54 | $aData = json_decode($sData, true); 55 | if ($aData && (is_object($aData)) || (is_array($aData) && !empty($aData))) { 56 | $result = $aData; 57 | } else { 58 | $result = $sData; 59 | } 60 | return $result; 61 | } else { 62 | return NULL; 63 | } 64 | } 65 | 66 | /** 67 | * @param $key 68 | * @param $hashKey1 69 | * @param null $hashKey2 70 | * @param null $hashKeyN 71 | * @return mixed 72 | */ 73 | public function hDel($key, $hashKey1, $hashKey2 = NULL, $hashKeyN = NULL) 74 | { 75 | return RedisClient::hDel(Cache::getPrefix() . $key, $hashKey1, $hashKey2, $hashKeyN); 76 | } 77 | 78 | /** 79 | * @param $sKey 80 | * @return mixed 81 | */ 82 | public function hLen($sKey) 83 | { 84 | return RedisClient::hLen(Cache::getPrefix() . $sKey); 85 | } 86 | 87 | /** 88 | * @param $sKey 89 | * @param $field 90 | * 91 | * @return bool 92 | */ 93 | public function hExists($sKey, $field) 94 | { 95 | return RedisClient::hExists($sKey, $field); 96 | } 97 | 98 | /** 99 | * @param $sKey 100 | * @param $field 101 | * @param $content 102 | * @param null $time 103 | * 104 | * @return bool|int 105 | */ 106 | public function hSet($sKey, $field, $content, $time = NULL) 107 | { 108 | if (is_array($content) || is_object($content)) { 109 | $bRes = RedisClient::hSet(Cache::getPrefix() . $sKey, $field, json_encode($content, true)); 110 | } else { 111 | $bRes = RedisClient::hSet(Cache::getPrefix() . $sKey, $field, $content); 112 | } 113 | self::redisExpire($sKey, $time); 114 | return $bRes; 115 | } 116 | 117 | /** 118 | * @param $sKey 119 | * @param $value 120 | * @param $count 121 | * @return mixed 122 | */ 123 | public function lRem($sKey, $value, $count) 124 | { 125 | return RedisClient::lRem(Cache::getPrefix() . $sKey, $count, $value); 126 | } 127 | 128 | /** 129 | * @param $sKey 130 | * @param $start 131 | * @param $end 132 | * 133 | * @return array 134 | */ 135 | public function lRange($sKey, $start, $end) 136 | { 137 | return RedisClient::lRange(Cache::getPrefix() . $sKey, $start, $end); 138 | } 139 | 140 | /** 141 | * @param $sKey 142 | * @return mixed 143 | */ 144 | public function lLen($sKey) 145 | { 146 | return RedisClient::lLen(Cache::getPrefix() . $sKey); 147 | } 148 | 149 | /** 150 | * @param $sKey 151 | * @param $value 152 | * @return mixed 153 | */ 154 | public function lPush($sKey, $value) 155 | { 156 | return RedisClient::lPush(Cache::getPrefix() . $sKey, $value); 157 | } 158 | 159 | /** 160 | * @param $sKey 161 | * @param $value 162 | * @return mixed 163 | */ 164 | public function rPush($sKey, $value) 165 | { 166 | return RedisClient::rPush(Cache::getPrefix() . $sKey, $value); 167 | } 168 | 169 | /** 170 | * @param $sKey 171 | * @return mixed 172 | */ 173 | public function rPop($sKey) 174 | { 175 | return RedisClient::rPop(Cache::getPrefix() . $sKey); 176 | } 177 | 178 | /** 179 | * @param $sKey 180 | * @return mixed 181 | */ 182 | public function lPop($sKey) 183 | { 184 | return RedisClient::lPop(Cache::getPrefix() . $sKey); 185 | } 186 | 187 | /** 188 | * @param $sKey 189 | * @param $value 190 | * @return mixed 191 | */ 192 | public function pfAdd($sKey, $value) 193 | { 194 | return RedisClient::pfAdd(Cache::getPrefix() . $sKey, $value); 195 | } 196 | 197 | /** 198 | * @param $sKey 199 | * @return mixed 200 | */ 201 | public function pfCount($sKey) 202 | { 203 | return RedisClient::pfCount(Cache::getPrefix() . $sKey); 204 | } 205 | 206 | /** 207 | * @param $sKey 208 | * @param $score1 209 | * @param $value1 210 | */ 211 | public function zAdd($sKey, $score1, $value1) 212 | { 213 | RedisClient::zAdd(Cache::getPrefix() . $sKey, $score1, $value1); 214 | return; 215 | } 216 | 217 | /** 218 | * @param $sKey 219 | * @param $start 220 | * @param $end 221 | * @return mixed 222 | */ 223 | public function zCount($sKey, $start, $end) 224 | { 225 | return RedisClient::zCount(Cache::getPrefix() . $sKey, $start, $end); 226 | } 227 | 228 | /** 229 | * @param $sKey 230 | * @param $start 231 | * @param $end 232 | * @return mixed 233 | */ 234 | public function zRemRangeByScore($sKey, $start, $end) 235 | { 236 | return RedisClient::zRemRangeByScore(Cache::getPrefix() . $sKey, $start, $end); 237 | } 238 | 239 | /** 240 | * @param $key 241 | * @param $ttl 242 | */ 243 | public function redisExpire($key, $ttl) 244 | { 245 | RedisClient::expire(Cache::getPrefix() . $key, $ttl ?: $this->getDefaultCacheTime()); 246 | } 247 | 248 | /** 249 | * @param $key 250 | * @param int $value 251 | * @param null $ttl 252 | * @return mixed 253 | */ 254 | public function incrementEx($key, $value = 1, $ttl = NULL) 255 | { 256 | $res = $this->increment($key, $value); 257 | $seconds = $this->getSeconds($ttl); 258 | $this->redisExpire($key, $seconds); 259 | return $res; 260 | } 261 | 262 | /** 263 | * @param $key 264 | * @param int $value 265 | * @param null $ttl 266 | * @return mixed 267 | */ 268 | public function decrementEx($key, $value = 1, $ttl = NULL) 269 | { 270 | $res = $this->decrement($key, $value); 271 | $seconds = $this->getSeconds($ttl); 272 | $this->redisExpire($key, $seconds); 273 | return $res; 274 | } 275 | 276 | /** 277 | * @param $key 278 | * @param $value 279 | * @return mixed 280 | */ 281 | public function sAdd($key, $value) 282 | { 283 | return RedisClient::sAdd(Cache::getPrefix() . $key, $value); 284 | } 285 | 286 | /** 287 | * @param $key 288 | * @return mixed 289 | */ 290 | public function sCard($key) 291 | { 292 | return RedisClient::sCard(Cache::getPrefix() . $key); 293 | } 294 | 295 | /** 296 | * @return mixed 297 | */ 298 | public function flushAll() 299 | { 300 | return RedisClient::flushAll(); 301 | } 302 | 303 | /** 304 | * @param $key 305 | * @return mixed 306 | */ 307 | public function sRandMember($key) 308 | { 309 | return RedisClient::sRandMember(Cache::getPrefix() . $key); 310 | } 311 | 312 | /** 313 | * @param $method 314 | * @param $arguments 315 | * @return mixed 316 | */ 317 | public function __call($method, $arguments) 318 | { 319 | return Cache::$method(... $arguments); 320 | } 321 | 322 | /** 323 | * @param $delay 324 | * @return Carbon 325 | */ 326 | protected function parseDateInterval($delay) 327 | { 328 | if ($delay instanceof DateInterval) { 329 | $delay = Carbon::now()->add($delay); 330 | } 331 | return $delay; 332 | } 333 | 334 | /** 335 | * @param $ttl 336 | * @return Carbon|int 337 | */ 338 | protected function getSeconds($ttl) 339 | { 340 | $duration = $this->parseDateInterval($ttl); 341 | 342 | if ($duration instanceof DateTimeInterface) { 343 | $duration = Carbon::now()->diffInRealSeconds($duration, false); 344 | } 345 | 346 | return (int)$duration > 0 ? $duration : 0; 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /src/Traits/AttributeStatusTrait.php: -------------------------------------------------------------------------------- 1 | getStatusLists(); 16 | } 17 | 18 | /** 19 | * @return mixed 20 | */ 21 | public function getStatusLists() 22 | { 23 | return $this->statusLists ?: ['停用', '启用']; 24 | } 25 | 26 | public function getStatusTextAttribute() 27 | { 28 | return $this->getStatusArrAttribute()[$this->status]; 29 | } 30 | 31 | /** 32 | * 状态范围查询(可传参指定要限定的状态范围,默认为大于0的内容) 33 | * 34 | * @param $query 35 | * @param array $status 36 | * 37 | * @return mixed 38 | */ 39 | public function scopeStatus($query, $status = []) 40 | { 41 | if (!is_array($status)) { 42 | $status = str2arr($status); 43 | } 44 | if (!empty($status)) { 45 | return $query->whereIn('status', $status); 46 | } 47 | return $query->where('status', '>', 0); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Traits/JsonResponseTrait.php: -------------------------------------------------------------------------------- 1 | $code['code'], 31 | 'message' => $code['message'], 32 | 'data' => $code['data'], 33 | ]; 34 | } else { 35 | $res = [ 36 | 'code' => $code, 37 | 'message' => $message, 38 | 'data' => $data, 39 | ]; 40 | } 41 | return array_merge($res, $attach); 42 | } 43 | 44 | 45 | /** 46 | * @param int $code 47 | * @param string $message 48 | * @param null $data 49 | * 50 | * @return \Illuminate\Http\JsonResponse 51 | * 返回值规范说明: 52 | * 1、成功正数(多种成功情况,不同的正数数字标示,原则上是不样的message对应不同的code) 53 | * 2、报错、失败、异常负数(返回数据集,但数据集为[]或null,不属于报错、失败、异常,所以视为成功,仅仅暂无数据而已) 54 | * 3、404、403、500等http status code可以均直接加上`-`号(如:-404),作为错误code,方便大家一目了然 55 | */ 56 | protected function apiResponse($code = FoundationResponse::HTTP_OK, $message = '', $data = NULL, $attach = []) 57 | { 58 | $res = $this->apiArray($code, $message, $data, $attach); 59 | if ($this->redirect_url) { 60 | $res['redirect_url'] = $this->redirect_url; 61 | } 62 | return Response::json($res)->setEncodingOptions(JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); 63 | } 64 | 65 | /** 66 | * @param string $message 67 | * @param null $data 68 | * @param int $code 69 | * @param array $attach 70 | * @return \Illuminate\Http\JsonResponse 71 | */ 72 | protected function success($message = '', $data = NULL, $code = FoundationResponse::HTTP_OK, $attach = []) 73 | { 74 | return $this->apiResponse($code, $message ?: 'Success', $data, $attach); 75 | } 76 | 77 | /** 78 | * @param string $message 79 | * @param null $data 80 | * @param int $code 81 | * @param array $attach 82 | * @return \Illuminate\Http\JsonResponse 83 | */ 84 | protected function error($message = 'Error', $data = NULL, $code = -1, $attach = []) 85 | { 86 | return $this->apiResponse($code, $message, $data, $attach); 87 | } 88 | 89 | /** 90 | * 设置 data.url 的值 91 | * 92 | * @param $url 93 | * @param array $param 94 | * 95 | * @return $this 96 | */ 97 | protected function redirectUrl($url, $param = []) 98 | { 99 | $this->redirect_url = url($url, $param); 100 | return $this; 101 | } 102 | } 103 | --------------------------------------------------------------------------------