php 框架运行的核心三步

  1. 从入口进入 index.php
  2. 解析 url,匹配路由
  3. 根据路由,调用控制器,渲染视图

tip: 在第一步到第二步之间,会有更多的操作。比如自动加载,容器初始化等。这些都是为了后面的准备。

Laravel

发音:

Laravel: /ˈlærəvel/【/let 罗 否/】

Lumen: /lu 门/

  • Laravel 是个功能齐全的全栈框架,学习她相当于你在学习成为全栈工程师。
  • 框架知识分类
  1. 底层实现知识 —— 如服务容器、服务提供器、Facades、Contracts、Repository 等

  2. 框架使用知识 —— 如用户注册登录、邮件发送、数据模型的 CRUD、用户数据获取等

Artisan

Artisan 是 Laravel 内置的命令行接口。它提供了一些有用的命令协助您开发,它是由强大的 Symfony Console 组件所驱动。利用它,我们可以快速的新建 Controller、Model等类。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
> php artisan optimize # 重置配置和路由的缓存文件,使用了此命令后不要在config目录外使用env()函数『众所周知,Laravel 的路由组件是出了名的慢』
> php artisan optimize:clear # 清空本地路由和配置缓存
> php artisan list  # 查看所有artisan命令<br/>
> php artisan make:model Models/User --migration # 创建 Eloquent 模型类和迁移类
> php artisan make:migration create_categories_table # 生成迁移类,常用规则:create_(数据表名称)_table, add_字段名称_to_xx_table, seed_(数据表名称)_table
> php artisan make:seeder seed_categories_data # 生成数据填充类[一般是用来生成假数据,开发测试时使用的]
> php artisan migrate # 数据库迁移
> php artisan db:seed # 往数据库填充假数据
> php artisan migrate:refresh --seed # 刷新数据库结构、清除已有数据并执行数据填充
> php artisan lang:publish zh-CN # 发布语言文件到项目里
> php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravelRecent" # 复制某个扩展的配置文件到config文件夹下
> php artisan make:auth
> php artisan make:scaffold Topic --schema="title:string:index,body:text,user_id:bigInteger:unsigned:index,category_id:integer:unsigned:index" # 资源脚手架:代码生成器,一键生成表 Topic 的模型、表、控制路、路由、视图等
> php artisan queue:listen # 常驻进程:启动队列系统并进入监听状态
> php artisan make:command CalculateActiveUser --command=larabbs:calculate-active-user # 创建 Artisan 命令
- php artisan tinker # 启动交互式shell

OTHER

  1. 框架核心内容

    app(): app(SlugTranslateHandler::class) => 获取应用实例

    • 类别名
    1
    2
    3
    
    // config/app.php 示例
    在 config.aliases 加上 'Auth' => Illuminate\Support\Facades\Auth::class 后
    在整个项目上可以直接用 \Auth::id() 方式获取当前用户id,可减少 use 的使用。
    
  2. .editorconfig文件:代码风格配置

    详解链接

    配置好代码风格后,在vs code上安装扩展EditorConfig for VS Code,这样就可以了。

  3. tinker: 是 Laravel 包含的一个强大 REPL,REPL 是 Read Eval Print Loop 的缩写,它是一种交互式 shell(即可交互式的编程环境),它接受单个用户输入,运行它们,并将结果返回给用户。

    参考链接

  4. 使用npm run production编译sass、js等文件,可以大大压缩js和css等文件的大小。

  5. Route::resource(‘users’, ‘UsersController’),resource 方法将遵从 RESTful 架构为用户资源生成路由。该方法接收两个参数,第一个参数为资源名称,第二个参数为控制器名称【隐性路由模型绑定】

    • 上面代码将等同于:
    • Route::get('/users', ‘UsersController@index’)->name(‘users.index’); // 列表
    • Route::get('/users/{user}', ‘UsersController@show’)->name(‘users.show’); // 信息展示页面
    • Route::get('/users/create', ‘UsersController@create’)->name(‘users.create’); // 新增页面
    • Route::post('/users', ‘UsersController@store’)->name(‘users.store’); // 保存新增功能
    • Route::get('/users/{user}/edit', ‘UsersController@edit’)->name(‘users.edit’); // 编辑页面
    • Route::patch('/users/{user}', ‘UsersController@update’)->name(‘users.update’); // 保存编辑功能
    • Route::delete('/users/{user}', ‘UsersController@destroy’)->name(‘users.destroy’); // 删除功能

    路由动态参数全局约束

  6. policy: 授权策略,用于做权限控制

    php artisan make:policy UserPolicy

    blade使用授权策略:@can(‘授权策略类的函数’, ‘授权策略类对应模型的实例’),eg: @can(‘update’, $user) @endcan

    控制器端使用授权策略:$this->authorize(‘update’, $user);

    Gates 和 Policies

    Laravel 授权的方式主要分两种:Gates 和策略(Policies)。

    Gates 和策略的关系像路由和控制器的。Gates 提供基于路由的授权方式;而策略将针对某个资源的操作逻辑组织起来,放在一个地方管理

    我们不需要在「项目里的授权,是选择使用 Gates,还是选择使用策略呢?」这个问题上纠结。许多项目里,都会混用这两种授权方式,而且运行良好。基本上,使用 Gates 的地方都是资源不相关的,比如查看管理员面板页;相反,策略是资源相关的,当你是具体授权某个资源的操作权限时,使用策略是没错啦。

  7. 隐性路由模型绑定:传输id,Laravel框架直接去获取id的实例对象

  8. 关联方法 Vs. 动态属性

    动态属性: eg: 模型类可以全局使用$this->数据库字段名

    参考图片

  9. Eloquent ORM

    • Eloquent 模型约定

      1
      2
      3
      4
      5
      6
      7
      8
      
      // $fillable 可以看作批量赋值的「白名单」, 你也可以使用 $guarded 属性来实现。 $guarded 属性包含的是不允许批量赋值的数组。也就是说, $guarded 从功能上将更像是一个「黑名单」。
      
      protected $connection = 'mysql_middle_office';
      protected $table = 'oat_customer';
      protected $guarded = ['customer_id'];
      protected $primaryKey = 'customer_id'; // Eloquent 也会假设每个数据表都有一个名为 id 的主键列。你可以定义一个受保护的 $primaryKey 属性来重写约定。
      public $incrementing = false; // 如果您希望使用非递增或非数字的主键则需要设置公共的 $incrementing 属性设置为 false。
      protected $keyType = 'string'; // 如果你的主键不是一个整数,你需要将模型上受保护的 $keyType 属性设置为 string
      
    • 本地作用域:允许我们在模型中定义通用的约束集合以便在应用中复用。要定义这样的一个作用域,只需简单在对应 Eloquent 模型方法前加上一个 scope 前缀,作用域总是返回 查询构建器。一旦定义了作用域,则可以在查询模型时调用作用域方法。在进行方法调用时不需要加上 scope 前缀。

    • 模型关联:默认关联数据是懒加载,使用预加载方法:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    // 预加载方式1
    // 此循环将执行一个查询,用于获取全部书籍,然后为每本书执行获取作者的查询。如果我们有 25 本书,此循环将运行 26 个查询:1 个用于查询书籍,25 个附加查询用于查询每本书的作者。
    // 谢天谢地,我们能够使用预加载将操作压缩到只有 2 个查询。在查询时,可以使用 with 方法指定想要预加载的关联(de方法名)
    
    // $books = App\Book::all();  // 懒加载
    $books = App\Book::with('author')->get();  // 预加载
    
    foreach ($books as $book) {
        echo $book->author->name;
    }
    
    // 执行预加载的sql示例
    // select * from books
    // select * from authors where id in (1, 2, 3, 4, 5, ...)
    
    // 预加载方式2:有可能你还希望在模型加载完成后在进行渴求式加载。举例来说,如果你想要根据某个条件动态决定是否加载关联数据,那么 load 方法对你来说会非常有用
    $books = App\Book::all();
    
    if ($someCondition) {
        $books->load('author', 'publisher');
        // $book->loadMissing('author', 'publisher');  // 希望关联关系仅在尚未加载时才去加载,以避免无效重复加载
    }
    
    • 访问器&修改器:当你在 Eloquent 模型实例中获取或设置某些属性值的时候,访问器和修改器允许你对 Eloquent 属性值进行格式化。
    • API资源:当构建 API 时,你往往需要一个转换层来联结你的 Eloquent 模型和实际返回给用户的 JSON 响应。
    • 常用方法
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    $user = App\Models\User::first();
    
    #  Laravel 5.8 查询存放反斜杠内容字段,需特殊处理
    $query->where('mall_order_infos.order_type', 'like', 'App\\Models\\Activity\\PreOrder');
    
    # 使用 isDirty() 方法确定模型或给定属性是否已被修改
    $user->name = 'Michael';
    $user->isDirty('title'); # true
    
    # 获取记录的原始属性
    $user->getOriginal('name');
    
    # Laravel 的模型可以通过 query 方法获取一个 Builder 实例,这种写法在一些场景下是有用的,比如说自定义过滤器
    $query = User::query();
    if( $request->name ){
        $query->where('name', $request->name);
    }
    
    # 打印执行 SQL 日志
    DB::enableQueryLog();
    dd(DB::getQueryLog());
    
    # 打印 SQL 语句
    $sql = User::where('age', 18)->toSql();
    dd($sql);
    
  10. 模型观察器

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    # 模型观察器
    - 对模型的生命周期内的多个时间点进行监控,分别有 ~ing  ~ed 事件
    // creating, created, updating, updated, saving,
    // saved,  deleting, deleted, restoring, restored
    - 每个监控方法接收 model 作为唯一参数
    # 使用观察器
    - 创建观察器文件,一个普通类,不需要继承什么
    - 针对需要的事件,编写对应的 ~ing  ~ed 方法,方法接收 model 作为唯一参数
    # 在 AppServiceProvider 中注册
    // 在 boot 方法中
    YourModel::observe(YourModelObserver::class);
    # 在模型下的 boot 方法中实现
    无论模型何时初始化,静态 boot() 方法自动执行,所以它是一个添加行为或者绑定事件的理想所在。比如,在我们当前的案例中,模型中发生删除事件时自动删除一个相关图片。
        public static function boot()
        {
            parent::boot();
    
            //当删除时触发
            self::deleted(function ($model)
            {
                Cache::forget(config('cache_keys.account') . $model->id);
                Cache::forget(config('cache_keys.account_wxid') . $model->wxid);
            });
        }
    
  11. Laravel Job 和 事件系统

    1
    2
    3
    4
    5
    6
    7
    
    - Job 和 队列 结合
    Job既可以用作同步,也可以用作异步。
    如果你想延迟执行一个操作,或者这个过程需要花费一段时间,那么就可以选择用Job,例如上传一个比较大的文件。
    Job一般用在正在处理的事情。比如我们去银行办理业务,很多人排队等待,我们可以把这条队看成一个队列queue,把每一个人看成一个Job,服务人员会帮我们一个接一个的处理业务。办完了一个业务,系统会叫号叫到下一个人,执行下一个Job。每个人需要办理的业务都不一样,这就是每个Job需要完成的任务。
    
    - Event
    事件监听可以允许参与不同的角色。事件监听可以认为是特定事件发生的一个Job,一旦事件创建,监听器就会触发。事件可以理解成“当...”,“就...”。 一个事件可以被多个监听器监听,比如登录后,系统既要发送邮件,又要发送短信,这个时候,就可以建立一个登录事件,事件触发后,同事被发送邮件和发送短信监听到。
    
  12. 表单请求验证类:将表单字段验证逻辑从控制器中解耦

    1
    2
    3
    4
    5
    6
    7
    8
    
    use App\Http\Requests\UserRequest;
    
    // 消息提示:with('success', '...') <=> session()->flash('success', '...')
    public function update(UserRequest $request, User $user)
    {
        $user->update($request->all());
        return redirect()->route('users.show', $user->id)->with('success', '个人资料更新成功!');
    }
    
  13. Facades(读音:/fəˈsäd/ )为应用程序的 服务容器 中可用的类提供了一个「静态」接口。你不必 use 一大串的命名空间,也不用实例化对象,就能访问对象的具体方法。

    • Facade 其实是一个容器中类的静态代理,他可以让你以静态的方式来调用存放在容器中任何对象的任何方法。
    • 创建自定义 Facade: 写好一个新功能后,先自定义一个 Facade 类后,然后在 Providers/…Provider.php 文件中的 register 方法中,将服务绑定到服务容器中。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    
    # 案例
    # app/Services/SocketIO/WeChat.php
    <?php
    
    namespace App\Services\SocketIO;
    
    /**
    * socket io 版的事件接口
    * Class WeChat
    * @package App\Services\SocketIO
    */
    class WeChat
    {
        const TEXT_MSG_TYPE = 1; //文本
        const IMAGE_MSG_TYPE = 2; //图片
        const AUDIO_MSG_TYPE = 3; //音频
        const VIDEO_MSG_TYPE = 4; //视频
        const NAMECARD_MSG_TYPE = 22; //名片
        const EMOJI_MSG_TYPE = 9; //表情
    
        /**
        * 获取消息类型对应的uri
        * @return array
        */
        public function getMsgTypeUris()
        {
            return [
                self::TEXT_MSG_TYPE => '/api/send_message_v2',
                self::IMAGE_MSG_TYPE => '/api/send_image_v2',
                self::EMOJI_MSG_TYPE => '/api/send_emoji_v2',
                self::NAMECARD_MSG_TYPE => '/api/send_namecard',
                self::CHATROOM_INVITE_MSG_TYPE => '/api/invite_friend_to_chatroom',
                self::VIDEO_MSG_TYPE => '/api/send_video',
            ];
        }
    }
    
    
    # app/Facades/WeChat.php
    <?php
    
    namespace App\Facades;
    
    use Illuminate\Support\Facades\Facade;
    
    class WeChat extends Facade
    {
        protected static function getFacadeAccessor()
        {
            return 'WeChat';
        }
    }
    
    # app/Providers/AppServiceProvider.php: 将服务绑定到服务容器中
    <?php
    
    namespace App\Providers;
    
    use App\Services\SocketIO\WeChat;
    
    class AppServiceProvider extends ServiceProvider
    {
        /**
        * Register any application services.
        * @return void
        */
        public function register()
        {
            $this->app->singleton('WeChat', function ()
            {
                return new WeChat();
            });
        }
    }
    
    # config/app.php
    <?php
        'providers' => [
            App\Providers\AppServiceProvider::class,
        ],
        'aliases' => [
            'WeChat' => App\Facades\WeChat::class,
        ],
    
  14. 消息通知类

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    <?php
    
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Illuminate\Auth\MustVerifyEmail as MustVerifyEmailTrait
    use Auth;
    
    class User extends Authenticatable implements MustVerifyEmailContract
    {
        // use Notifiable;
    
        // trait 中的 notify 方法重命名为 laravelNotify
        use Notifiable {
            notify as protected laravelNotify;
        }
    }
    
    
    Auth::user()->notify();  // 推送消息通知
    Auth::user()->notifications()->get(); // 获取该用户所有的通知列表
    Auth::user()->readNotifications()->get();  // 获取已读的通知列表
    Auth::user()->unreadNotifications()->get();  // 获取未读的通知列表
    Auth::user()->unreadNotifications->markAsRead();  // 将未读标记为已读
    Auth::user()->readNotifications->markAsRead();  // 将已读标记为纬度
    
  15. Services层:使用 Traits 来为数据模型瘦身

    namespace Models/Traits;

  16. 本地化(或者多语言系统处理方案)

    • 客户端请求 API 时, 加上 HTTP 的 Accept-Language 头信息,便于服务器区分系统语言。
    • 从接口的可扩展性、适用性和专业性上考虑,最合理的也是最推荐的做法是:API 既提供错误码,又提供本地化的错误消息。
    • 另外,错误消息 默认 返回英文,也会是比较合理的最佳实践,当然最终视 API 业务逻辑而定。
  17. 切记:config目录里用 env() 获取环境变量,其他地方用 config() 获取环境变量。

    • 因为线上环境启用 config 缓存后,config 文件夹外的 env 函数不起效果
  18. 开发环境记录程序执行的 sql 语句方案

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    // App\Providers\AppServiceProvider
    public function boot()
    {
        if (env('APP_ENV') == 'local') {
            DB::listen(function ($query) {
                $sql = str_replace("?", "'%s'", $query->sql);
                $sql = vsprintf($sql, $query->bindings);
                $sql = str_replace("\\", "", $sql);
                Log::info($sql);
            });
        }
    }
    
  19. Laravel 指定日志文件记录任意日志

    1
    2
    3
    4
    5
    
    use Illuminate\Support\Facades\Log;
    
    Log::getMonolog()->popHandler();
    Log::useFiles(storage_path('logs/data_info_market.log'), 'info');
    Log::info('==>id=1111');
    
  20. 使用 chunk(分块) 和 cursor(游标) 减少内存的使用量

词汇

  1. mass assignment => 批量赋值
  2. fillable => 用户可赋值字段,guarded => 仅保护字段
  3. reguarded => 保护,unguarded => 取消保护
  4. pivot => 它代表中间表的一个模型对象

规范

  • 遵守『约定优于配置』设计范式
  • 使用复数形式命名:控制器、数据库表名、文件夹名
  • 其他使用单数形式命名,如model、policy、seeder

全局辅助方法

  1. session()
  2. redirect()
  3. csrf_token(), csrf_field()
  4. snake_case() => 驼峰法字符串格式化为下划线命名。
  5. config(‘app’) => 获取配置文件的数据,可以使用点语法获取具体参数

中间件

Laravel 中间件提供了一种方便的机制来过滤进入应用的 HTTP 请求。类似CI框架的钩子。

  1. auth: 控制已登录用户才能访问的函数
  2. guest:控制游客才能访问的函数

Auth 类

  1. use Auth; 等价于 use Illuminate\Support\Facades\Auth;
  2. Auth::loginUsingId(1); // 登录指定用户 ID 的用户到应用上
  3. Auth::user() // 获取当前用户实例
  4. Auth::check() // 判断是否已登录
  5. Auth::id() <=> Auth::user()->id; // 获取id
  6. Auth::once($credentials); // 只针对一次的请求来认证用户
  7. Auth::logout(); // 使用户退出登录(清除会话)

Blade

  • Request::url() == route(‘categories.show’, 4 ) // 判断当前请求链接和某路由是否一致
  • Blade 语法 {{ }} 会自动调用 PHP htmlspecialchars 函数来避免 XSS 攻击。
  • Blade 的 {!! !!} 语法是直接数据,不会对数据做任何处理。
  • @include(‘layouts._header’, []) , @includeWhen(Auth::check(), ‘layouts._header’, [])

项目实践案例

  1. PhpStorm Ide Helper安装

    • 1、在PhpStorm中搜索安装 Laravel Plugin

    • 2、composer require --dev barryvdh/laravel-ide-helper

    • 3、如果你只在开发环境中安装「larave-ide-helper」,那么可以在「app/Providers/AppServiceProvider.php」的「register」方法中写入下面代码:

    1
    2
    3
    4
    5
    6
    7
    
    public function register()
    {
        if ($this->app->environment() === 'local') {
            $this->app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
        }
        // ...
    }
    
    • 4、php artisan ide-helper:generate - 为 Facades 生成 phpDocs 注释

    • 5、php artisan ide-helper:meta - 为 PhpStorm 生成类路径提示文件

  2. mergeBindings方式查询 和 子连接查询

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    
    // mergeBindings方式查询
    $subQuery = MemberActivity::table(MemberActivity::getMonthTableName(strtotime('-1 month')))::query()
        ->where('chatroom_id', $chatroomId)
        ->select(['member_id', 'date'])
        ->orderByDesc('id');
    $query = MemberActivity::table()::query()
        ->where('chatroom_id', $chatroomId)
        ->select(['member_id', 'date'])
        ->orderByDesc('id')
        ->union($subQuery);
    $queryUnionSql = $query->toSql();
    $lastActivityData = DB::connection("mysql_big_data")
        ->table(DB::raw("($queryUnionSql) as temp"))
        ->mergeBindings($query->getQuery()) // 子查询语句参数实例化
        ->groupBy('member_id')
        ->pluck('date', 'member_id')
        ->toArray();
    
    // 子连接查询
    public function getTraceLatestList(array $ownerAccountIds, array $bindAccountIds): array
    {
        $subQuery = \App\Models\Trace::query()
            ->select(DB::raw("max(id) max_id"))
            ->whereIn('account_id', $ownerAccountIds)
            ->whereIn('target_account_id', $bindAccountIds)
            ->groupBy(DB::raw("concat(account_id, '-', target_account_id)"));
    
        $ret = \App\Models\Trace::query()
            ->select([DB::raw("concat(traces.account_id, '-', traces.target_account_id) as account_key"), 'traces.content'])
            ->joinSub($subQuery, 'sub', function ($join) {
                $join->on('traces.id', '=', 'sub.max_id');
            })
            ->whereIn('traces.account_id', $ownerAccountIds)
            ->whereIn('traces.target_account_id', $bindAccountIds)
            ->pluck('traces.content', 'account_key')
            ->toArray();
    
        return $ret;
    }
    
    // 子查询案例
     $data = TableA::query()
        ->select($fields)
        ->whereIn(
            'customer_id',
            TableB::query()->whereIn('account_id', $ownerAccountIds)->select(['customer_id'])
        )
        ->orderByDesc('customer_id')
        ->paginate($params['per_page'])->toArray();
    
  3. Laravel 数据库模式非 ORM 模式 获取的数据数组化方式

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    $data = DB::connection("mysql")
        ->table("table_name")
        ->where('id', 1)
        ->orderByDesc('created_at')
        ->take(100)
        ->get()
        ->map(function ($x) { // 关键地方
            return (array) $x;
        })
        ->toArray();
    
  4. 迁移文件表添加表注释

    1
    2
    3
    4
    5
    
    \DB::statement("ALTER TABLE `categories` comment '帖子分类'");
    
    // 创建时间和更新时间
    $table->timestamp('created_at', 0)->useCurrent();
    $table->timestamp('updated_at', 0)->default(\DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
    
  5. 服务器环境修改了数据库密码、等配置时,需要执行下 php artisan optimize # 重置配置和路由的缓存文件

  6. Laravel 查询语句指定索引( mysql 强制索引)

    1
    2
    3
    4
    5
    6
    
    $agents = Agent::query()
        ->from(\DB::raw('`agent` FORCE INDEX (`index_test`)'));
        ->join(\DB::raw('`user` FORCE INDEX (`user_id`)'), function ($join) use ($staffId) {
            $join->on('agent.user_id', '=', 'user.user_id');
        })
        ->get();
    

Laravel Install

  1. 方法一: 安装器安装

    1
    2
    3
    4
    5
    
    # 缺点不能安装指定版本,默认安装最新版本
    
    composer global require "laravel/laravel-installer"
    
    lumen new test
    
  2. 方法二:通过 Composer Create-Project 命令安装,可以指定版本号

    1
    2
    3
    
    cd ~/www/
    
    composer create-project laravel/laravel test --prefer-dist '5.8.*'
    
  3. 查看版本号

    1
    2
    3
    
    cd ~/www/your_project
    
    php ./artisan
    

Laravel 构建已有项目流程

  1. 修改配置文件 .env

    包括数据库配置、邮箱配置、redis配置、时区配置等

  2. 组件安装

    1
    
    composer install
    
  3. 数据库表迁移和数据填充

    1
    2
    
    # 执行数据库迁移和数据填充
    php artisan migrate:refresh --seed
    

Laravel 创建新项目流程

  1. 框架安装

    1
    2
    3
    
    cd ~/Code/
    
    composer create-project laravel/laravel laravel-test --prefer-dist '5.8.*'
    
  2. 更改 readme.md

  3. 统一代码风格

    1
    2
    3
    4
    
    # .editorconfig 文件添加以下代码
    [*.{js,html,blade.php,css,scss}]
    indent_style = space
    indent_size = 2
    
  4. 修改配置文件 .env

    包括数据库配置、邮箱配置、redis配置、时区配置、语言包配置等

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    # 配置时区
    1. .env 文件添加:TIMEZONE="asia/shanghai"
    2. 更改 config/app.php : 'timezone' => env('TIMEZONE', 'UTC'),
    
    # 添加中文语言包
    1. composer require "overtrue/laravel-lang:~3.0"
    
    2. 安装成功后,在 config/app.php 文件中将以下这一行:
    Illuminate\Translation\TranslationServiceProvider::class,
    替换为:
    Overtrue\LaravelLang\TranslationServiceProvider::class,
    
    3. .env 文件添加 : LOCALE="zh-CN"
    
    4. 更改 config/app.php : 'locale' => env('LOCALE', 'en')
    
  5. 数据库表迁移和数据填充

    1
    2
    
    # 执行数据库迁移和数据填充
    php artisan migrate:refresh --seed
    
  6. 基础布局

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    # Models
    mkdir app/Models
    mv app/User.php app/Models/User.php
    在执行上面的操作之后,我们还需要执行下面这两个操作:
    1、修改 Models/User.php 文件,更改 namespace 为我们新创建的文件夹路径。
    2、编辑器全局搜索 App\User 替换为 App\Models\User。
    
    # Views
    rm resources/views/welcome.blade.php
    
    mkdir resources/views/layouts
    touch resources/views/layouts/app.blade.php
    touch resources/views/layouts/_header.blade.php
    touch resources/views/layouts/_footer.blade.php
    
    mkdir resources/views/shared
    touch resources/views/shared/_messages.blade.php
    
    # 运行Laravel Mix
    vi resources/sass/app.scss => 删除 Fonts
    vi ./webpack.mix.js => 加上 version(),解决浏览器对静态文件的缓存问题
    yarn config set registry https://registry.npm.taobao.org
    yarn install => 安装依赖
    npm run watch-poll
    
  7. 加上授权策略自动发现的逻辑(Laravel 5.8)

    1
    2
    3
    4
    5
    6
    
    // 自动授权默认会假设 Model 模型文件直接存放在 app 目录下,鉴于我们已将模型存放目录修改为 app/Models,接下来还需自定义自动授权注册的规则,修改 boot() 方法:
    // 在 app/Providers/AuthServiceProvider.php 中的 boot 方法中加上授权策略自动发现的逻辑
    Gate::guessPolicyNamesUsing(function ($modelClass) {
        // 动态返回模型对应的策略名称,如:// 'App\Models\User' => 'App\Policies\UserPolicy',
        return 'App\Policies\\'.class_basename($modelClass).'Policy';
    });
    
  8. 项目部署相关命令「可选」

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    # 迁移队列任务执行失败记录表
    php artisan queue:failed-table
    php artisan migrate
    
    # 迁移通知消息表
    php artisan notifications:table
    
    # 安装 redis 依赖包
    composer require predis/predis "~1.0"
    
    # 安装 HTMLPurifier,HTMLPurifier 本身就是一个独立的项目,运用『白名单机制』对 HTML 文本信息进行 XSS 过滤。这种过滤机制可以有效地防止各种 XSS 变种攻击。
    composer require "mews/purifier:~2.0"
    php artisan vendor:publish --provider="Mews\Purifier\PurifierServiceProvider"
    
    # 构建系统管理员后台
    composer require "summerblue/administrator:~1.1"
    php artisan vendor:publish --provider="Frozennode\Administrator\AdministratorServiceProvider"
    
    # Laravel开发者工具类
    1. 代码生成器
    > composer require "summerblue/generator:~1.0" --dev
    
    2. 调试工具
    > composer require "barryvdh/laravel-debugbar:~3.2" --dev
    
    3. 账号切换工具:测试用户权限将会很方便
    > composer require "viacreative/sudo-su:~1.1" --dev
    
    4. 安装 Horizon, Horizon 是 Laravel 生态圈里的一员,默认只能在 local 环境中访问仪表盘,为 Laravel Redis 队列提供了一个漂亮的仪表板,允许我们很方便地查看和管理 Redis 队列任务执行的情况。
    > composer require "laravel/horizon:~3.1" --dev
    > php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider" # 至此安装完毕,浏览器打开 http://hosts/horizon 访问控制台:
    > php artisan horizon # 队列监控,用来代替 Laravel 自带的 artisan queue:listen,需要常驻运行
    > Tip: 需要注意的是,artisan horizon 队列工作的守护进程是一个常驻进程,它不会在你的代码改变时进行重启,当我们修改代码以后,需要在命令行中对其进行重启操作。
    
    5. 查询日志组件:可以查看sql的输出
    composer require overtrue/laravel-query-logger --dev
    

Laravel IDE Helper

Laravel IDE Helper 是一个极其好用的代码提示及补全工具,可以给编写代码带来极大的便利。

1
2
3
4
5
6
# 安装 larave-ide-helper#
# 如果只想在开发环境安装请加上 --dev
composer require barryvdh/laravel-ide-helper

php artisan ide-helper:generate - 为 Facades 生成注释
php artisan ide-helper:meta - 生成 PhpStorm Meta file