沙滩星空的博客沙滩星空的博客

Laravel开发过程中需要注意的坑

Laravel 无疑是一个优秀的Web开发框架,优雅的语法和封装,现成的解决方案,让人无需考虑太多底层的东西。但是,这必须在对框架本身熟悉的前提下,才能游刃有余。即便是老手,没注意看文档,也会栽坑里。


测试环境: Laravel 版本:6.18.35

新增服务提供者不生效

此问题源于 模型的多态关联,数据库设计时,没有按照 Laravel 约定,设置关联类型字段为字符串,这边设计为整型。必须使用 自定义多态类型 。做一个 morph 映射:设置整数字段的枚举值,映射到数据模型的类名。
例: 评论数据表,为了区分是文章评论,还是视频评论,新增了 commentable_type 字段,0为文章评论,1为视频评论。

下面是官方文档,关于 自定义多态类型 的说明:

不过,你可能希望数据库与应用的内部结构解耦。在这种情况下,可以定义一个 「morph 映射」 来通知 Eloquent 使用自定义名称代替对应的类名:

use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
    0 => 'App\Post',
    1 => 'App\Video',
]);

可以在 AppServiceProvider 的 boot 函数中注册 morphMap,或者创建一个单独的服务提供者

不过,这边是 创建一个单独的服务提供者 ,但是一直没有生效。排查了许久。最后使用如下命令解决:

 php artisan config:cache

因为新增加的服务提供者,根本没有加入到配置列表。通过以上命令才会生效。


配置文件密码包含 #

.env 文件中,数据库密码不能使用#,否则解析的时候#后面的部分会被当做注释从而导致密码解析错误

解决:用单引号或双引号将密码字符串包裹

DB_PASSWORD="password#1234"

路由解析匹配顺序

正常情况路由列表匹配顺序为:从路由文件,由上往下匹配。
一条路由记录符合,就不再匹配下一条。如下所示:

正确:

Route::get('/posts/create','PostController@create');
Route::get('/posts/{post}','PostController@show');

错误:

Route::get('/posts/{post}','PostController@show');
Route::get('/posts/create','PostController@create');

然而,使用 redirect 方法,重定向路由。实际却是反过来的,与上述经验不符:

Route::get('/', 'HomeController@index');
// 虽然路由表解析顺序是从上往下匹配,但是,下面这段 redirect 要放在 Route::get("/")下面才有效
Route::redirect('/', '/admin/users');

数据迁移

    Schema::create("user_coupons", function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedInteger('cost_points')->default(0)->comment('花费积分'); // 不允许为null,默认0
        $table->boolean('validate')->nullable()->default(0)->comment('是否有效'); // 允许为null,默认0.
        $table->timestamp('used_at')->nullable()->comment('使用时间'); // 允许null, 默认null
        $table->timestamp('deleted_at')->nullable(); // 允许null, 默认null
        $table->timestamps();
    });

定时任务log日志写入失败问题

原因:

宝塔调用 artisan 命令,每天凌晨执行定时任务。
按天切割日志后,artisan 命令,每天首先生成 laravel-{Y-m-d}.log 日志,权限为 root
而网站应用,正常以 php-fpm 模式运行。通常是以 www 用户的权限,来生成或读写文件。
所以,命令模式以 root 权限创建 log 文件, web 程序以 www 权限对 log 日志文件写入失败。
解决:

cd /www/wwwroot/league && php artisan schedule:run

改为:

cd /www/wwwroot/league && su www -s /bin/bash -c "php artisan schedule:run"

或者(未验证):

$app->configureMonologUsing(function(Monolog\Logger $monolog) {
    $filename = storage_path('logs/laravel-'.php_sapi_name().'.log');
    $handler = new Monolog\Handler\RotatingFileHandler($filename);
    $monolog->pushHandler($handler);
});

保存数据时,空字符自动转化为 NULL 问题

有一个 ConvertEmptyStringsToNull 中间件,自动将空字符串转为 null。
在 AppHttpKernel.php 中,注释了这个中间件就好了

App\Http\Kernel.php
......
    protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
//        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];
......

数据库版本低于5.7报错

mysql 数据库版本低于5.7时,执行 php artisan migrate 后报错:

PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes")

解决:

在AppServiceProvider添加代码: Schema::defaultStringLength(191);

vim app/Providers/AppServiceProvider.php

use Illuminate\Support\Facades\Schema;
......
public function boot()
{
    Schema::defaultStringLength(191);
}
......

Eloquent 默认属性值为空字符串 ( ‘’) 的时候,自动转为 null 的问题 https://learnku.com/laravel/t/35052

详解Laravel设置多态关系模型别名的方式 https://www.jb51.net/article/172181.htm

Laravel 日志权限变成 Root 处理 https://www.phpriji.cn/blog/detail/20180713142308qvpcnu.html
artisan日志-root权限-www不能访问解决办法 https://blog.csdn.net/u013866352/article/details/105402716

未经允许不得转载:沙滩星空的博客 » Laravel开发过程中需要注意的坑

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址