time 20210309
author Venki
基于git的分支解释
master分支
- 主分支 , 产品的功能全部实现后 , 最终在master分支对外发布。
feature分支
- 功能开发分支 , 基于develop分支克隆 , 主要用于新需求新功能的开发。
hotfix分支
- 补丁分支 , 基于master分支克隆 , 主要用于对线上的版本进行BUG修复。
develop分支
- 主开发分支 , 基于master分支克隆。
release分支
- 测试分支 , 基于feature分支合并到develop之后, 从develop分支克隆。
开发中遇到
路由route的访问
RouteServiceProvider
此类中对路由的访问进行了限制
routes/api.php 文件中定义的路由通过 RouteServiceProvider 被嵌套到一个路由组里面。
在这个路由组中,会自动添加 URL 前缀 /api 到此文件中的每个路由,这样你就无需再手动添加了。你可以在 RouteServiceProvider 类中修改此前缀以及其他路由组选项。
Route
路由文件下面一直显示波浪号
# 解决方法
# 安装提示插件
composer require barryvdh/laravel-ide-helper
php artisan ide-helper:generate
- 'Route Group’分组的参数
/**
* 只要指明了命名空间,那么在子路由中所使用的所有控制器都位于App\Http\Controller\Admin这个命名空间下。
*/
Route::group(['namespace' => 'Admin', 'prefix' => 'admin'], function(){
/**
* 其实HomeController在App\Http\Controller\Admin这个命名空间下。
*/
Route::get('/', 'HomeController@index');
});
/**
* 跟普通路由一样 也是用as来命名但是首字母最好大写后面跟俩冒号 代表它是一个分组 如果这样写 我们就可以通过 route('Admin::index')方式来找到它了
*/
Route::group(['namespace' => 'Admin', 'prefix' => 'admin', 'as' => 'Admin::'], function(){
Route::get('/', ['as' => 'index','uses' => 'HomeController@index']);
});
找到控制器
Laravel Target class [控制器名称] does not exist.完美解决!
找到Providers文件下的RouteServiceProvider文件,然后找到protected $namespace = 'App\\Http\\Controllers';
无添加即可。
多环境配置文件
方式有两种,一种是通过服务器的名称来判断采用哪个配置文件,另一种则是通过域名判断使用哪个配置文件。
# 方法一:
$env = $app->detectEnvironment(
function () use ($app) {
$uname = php_uname('n');
$environment = 'local';
switch ($uname) {
case 'xxx1':
case 'xxx2':
$environment = 'production';
break;
case 'xxx3':
$environment = 'testing';
break;
default:
$environment = 'local';
break;
}
putenv("APP_ENV={$environment}");
(new \Dotenv\Dotenv($app->basePath(), ".env.{$environment}"))->load();
}
);
# 方法二:
$app->loadEnvironmentFrom(call_user_func(function(){
$my_http_host = strtolower($_SERVER['HTTP_HOST']);
switch ($my_http_host){
case 'www.abc.com':
$myenv = 'production';
break;
case 'test.abc.com':
$myenv = 'develop';
break;
default:
$myenv = 'local';
break;
}
$myenv = '.' . $myenv . '.env';
return $myenv;
}));
创建资源控制器
php artisan make:controller Admin\V1\AuthController --resource
资源路由
Route::resource('admin', 'AdminController', ['names' => [
'index' => 'admin.index',
'create' => 'admin.create',
'store' => 'admin.store',
'show' => 'admin.show',
'edit' => 'admin.edit',
'update' => 'admin.update',
'destroy' => 'admin.destroy'
]]);
# 或者下面这种类型
Route::resource('admin', 'AdminController')->names([
'show' => 'admin.show',
'store' => 'admin.store',
]);
请求方法 | 请求URL | 对应控制器方法 | 代表的意义 |
---|---|---|---|
GET | /admin | index | 列表 |
GET | /admin/create | create | 创建(显示表单页) |
POST | /admin | store | 保存创建的数据表单 |
GET | /admin/{id} | show | 显示对应id的内容 |
GET | /admin/{id}/edit | edit | 编辑(显示表单页) |
PUT/PATCH | /admin/{id} | save | 保存编辑的数据表单 |
GET | /admin/{id} | destory | 删除 |
表单验证
- 表单验证将控制器中一部分逻辑判断剥离出来单独成文,便于解耦维护。
表单验证中的authorize方法主要作用:关于授权方法的目的:授权方法通常用于根据您要尊重的某些策略授权实际请求.例如,如果您有编辑Post模型的请求,则在authorize方法中,您将检查尝试编辑帖子的特定用户是否具有执行此操作的权限(例如,作为帖子的作者),即使您想使用中间件进行授权,也没关系.无论如何,通常表单请求中的授权方法用于对特定请求进行授权检查.总之:如果您在中间件中执行身份验证和授权任务,则无需在授权方法中重复这些任务,但请记住,该方法的本机用途是授权特定请求。其实就是说,每个表单严重的权限再次验证主要是针对特定请求而言的,当然也可以通过路由+特定的中间件实现,各有所长吧。
handler异常类处理点击阅读
# 报错
Declaration must be compatible with ExceptionHandler->report
- 对于Laravel <7:应用程序App\Exceptions\Handler类的report和render方法 应接受Exception接口实例, 而不是Throwable实例:
use Exception;
public function report(Exception $exception);
public function render($request, Exception $exception);
- 对于Laravel> = 7:应用程序App\Exceptions\Handler类的report和render方法 应接受Throwable接口实例, 而不是Exception实例:
# Throwable编辑器提示我只有切换成PHP7.0方可使用
use Throwable;
public function report(Throwable $exception);
public function render($request, Throwable $exception);
辅助函数helper的引入
1. 在APP下面添加helper.php文件
2. 在composer.json下面的autoload添加`"files": [
"app/helpers.php"
]`
3. 执行composer dump-autoload加载执行即可。
如何理解laravel的看守器和用户提供器
- 看守器:guard指定想要使用的看守器实例。这允许你使用完全独立的可验证模型或用户表来管理应用程序各个部分的验证。就是值验证凭证,通过不同的认证方式验证不同的应用。
- 用户提供器:其实就是提供用户认证的方式可以是eloquent,也可以是database的table方式。
- 一句话描述两者的关系:通过eloquent提供用户支撑,然后通过jwt的方式进行认证管理看守。
- guard可以理解为一扇门,想进去这扇门必须有钥匙,而铸造这把钥匙需要很多数据支撑,这个就是用户提供器provider的作用。
关于排序规则
- utf8mb4_general_ci:ci即case-insensitive,不区分大小写。没有实现Unicode排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。
- utf8mb4_unicode_ci:是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。
- utf8mb4_general_ci是一个遗留的 校对规则,不支持扩展,它仅能够在字符之间进行逐个比较。utf8_general_ci校对规则进行的比较速度很快,但是与使用utf8mb4_unicode_ci的校对规则相比,比较正确性较差。
- general_ci 更快,unicode_ci 更准确。但相比现在的CPU来说,它远远不足以成为考虑性能的因素,索引涉及、SQL设计才是。使用者更应该关心字符集与排序规则在db里需要统一。(可能产生乱码的字段不要作为主键或唯一索引。例如:以url来作为唯一索引,但是它记录的有可能是乱码。)
关于API资源的理解
- 资源和资源集合:资源是将单个模型转换成数组,而资源集合是将模型的集合转换成数组。并不是必需得为每一个模型类都定义一个资源集合类,因为所有资源都有提供一个 collection 方法来动态生成一个「临时」资源集合
use App\Http\Resources\User as UserResource;
use App\Models\User;
Route::get('/user', function () {
return UserResource::collection(User::all());
});
- 如果你需要自定义返回集合的元数据,则仍需要定义一个资源集合:
- 默认情况下,当资源响应被转换成 JSON 时,顶层资源将会被包裹在 data 键中。因此一个典型的资源集合响应如下所示:
{
"data": [
{
"id": 1,
"name": "Eladio Schroeder Sr.",
"email": "therese28@example.com",
},
{
"id": 2,
"name": "Liliana Mayert",
"email": "evandervort@example.com",
}
]
}
- 如果你想使用自定义键而不是 data,可以在资源类上定义 $wrap 属性:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class User extends JsonResource
{
/**
* 应该应用的「数据」包装器
*
* @var string
*/
public static $wrap = 'user';
}
postman进行全局设置token时,只需要在login登录时设置即可,无须再在其他请求中设置。
auth 中间件无法获取用户信息,是因为没有指定guard进行获取
# 指定guard,因为默认配置是web
Auth::guard($guard)->user();
权限管理laravel-permission
- 复合索引长度限制为(1000个字符),所在在进行数据迁移时,会报错,修改的方法如下:指定字符串长度。
$table->string('model_type', 191);
$table->unsignedBigInteger($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type']);
获取路由参数
- 请求严重分为两类:参数验证和业务验证。
- 类似于以下请求,该如何进行验证
# 参数值是1001,但是没有参数变量
/access/adm/v1/admin/1001
# 打印下列语句
dd($this->route());
# 看到有如下信息:
+parameters: array:1 [
"admin" => "1001"
]
# 默认参数名字就是admin,所以获取此参数值即可
$this->route()->parameter('admin')
- 获取参数值如何进行验证
# 对于restfullapi中的show路由的参数验证,为了保持路由不变,只需要进行业务类验证即可!
整型转换用int还是intval()合适?(我用int)
- intval 和 (int) 都不可以转换 Object;
- 转换效率 (int)>intval()>sprintf(intval是PHP内置的方法,效率相对低);
- 输入0123, 0x123 (int)函数也会按八进制和十六进制转换;
模型关联中的with用法
# 有时,你可能希望预加载一个关联,同时为预加载查询添加额外查询条件,就像下面的例子:
$users = App\Models\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
$enable_function = function ($query) {
$query->enable();
};
$roles = Role::with(['permissions'=>$enable_function,'menus'=>$enable_function])->get();
scope的用法
- 使用场景:在项目中经常会面对一些条件的查询,这些查询条件好些是相同的。scope 可以实现这些相同条件的复用.参考
trans 自定义错误抛出时
# 没有按照自定义的中文抛出,原因是:
The menus field must be present.
# 丢掉了*
return [
'name.*' => trans('admin/v1/request.role.name'),
'menus.*' => trans('admin/v1/request.role.menus'),
'permissions.*' => trans('admin/v1/request.role.permissions'),
'is_enable.*' => trans('admin/v1/request.role.is_enable'),
];
ignore
- 忽略指定记录的唯一验证,比如:权限管理中的角色更新,如果更新的这条记录的名称没有任何变动就不需要验证,也就是说验证是忽略本条修改记录之外的验证,如果该条记录的角色名称改变了,但是除了本条记录为与其他记录的角色名称冲突了,那就不行,此时就需要验证。总之就是:验证唯一性时忽略本条记录验证。
created_at 和 updated_at
- laravel默认创建数据表时,这两个字段是自动维护的,如果不想取这两个字段名字,但是又想保持自动维护,可以在模型添加以下的属性
const CREATED_AT = 'created_time';
const UPDATED_AT = 'updated_time';
路由分组以及中间件分组遇到的问题
# 无效
Route::group(['middleware' => ['admin.login.auth'], ['admin.permission']], function () {
# 改成这样
Route::group(['middleware' => ['admin.login.auth', 'admin.permission']], function () {
错误码设置
- 错误码切记不要以0开头,比如
011023
会进行禁止转换。