Laravel学习笔记持续更新中

Laravel学习笔记

一、简介

1. 安装

composer create-project laravel/laravel=6.0.* --prefer-dist blog

二、路由的使用

1. 文件位置

  • /routes/web.php web网页的路由
  • /routes/api.php api接口的路由
  • /routes/console.php 终端的路由,php artisan inspire
  • /routes/channels 待补充

2. 基本使用

2.1 根路由
<?php
  Route::get('/', function () { return 'this is root route'; });
2.2 请求方式
<?php
Route::get('/users', function () {});
Route::post('/users', function () {});
Route::put('/users', function () {});
Route::patch('/users', function () {});
Route::delete('/users/1', function () {});
Route::options('/users', function () {});
2.3 matchany 的使用
<?php

// 匹配指定规则路由
Route::match(['get', 'post'], '/users', function () {});

// 匹配任何路由规则
Route::any('foo', function () {});
2.4 资源路由
<?php
Route::resource('/users', UsersController::class);

3. 参数

3.1 必选参数
  • 格式: {param}

  • 举例

    <?php
    Route::get('/users/{id}', 'UsersController@edit');
    
3.2 可选参数
  • 格式: {param?}

  • 举例

    <?php
    Route::get('/users/{id?}', 'UsersController@edit');
    
3.3 别名
  • 格式:->name('alias name')

  • 举例

    <?php
    Route::get('/aaa/bbb/ccc/ddd/eee/fff', 'XxxController@xxx')->name('abcdef');
    
  • 调用方式:route('abcedf')

3.4 使用 artisan 查看路由列表
  • 命令:php artisan route:list
3.5路由群组
  • 格式:group

  • 举例

    <?php
    Route::group(['prefix' => 'admin'], function () {
      Route::get('menus', function () {}); // 匹配路由:/admin/menus
    });
    

三、控制器

1. 文件位置

  • /app/Http/Controllers

2. 命名格式

  • 格式:大写驼峰+Controller.php
  • 举例:商品控制器:GoodsController.php
  • 使用 artisan 创建:php artisan make:controller GoodsController

3. 接收用户参数

  • 使用的类路径:Illuminate\Support\Facades\Request
  • 获取方式:
    • Request::get('参数名称', '默认值');
    • Request::all(); // 获取用户的所有参数
    • Request::get(''); // 获取 get 参数
    • Request::only([]); // 获取指定的几个参数
    • Request::except([]); // 排除指定的几个参数
    • Request::has('name'); // 判断参数是否存在

四、DB 类操作数据库

1. 文件所在位置

  • Illuminate\Support\Facades\DB::class

2. 基本操作

2.1 增加
  • insert

    • 使用 table('表名') 再进行插入,返回 bool 类型

      <?php
      $db = DB::table('user');
      $db->insert(['nickname' => 'xfjpeter', 'email' => 'fsyzxz@163.com']); // 返回布尔类型的值
      
    • 直接使用 ::insert('sql语句') 插入,返回 bool 类型

      <?php
      DB::insert('insert into user(nickname, email) values("xfjpeter", "fsyzxz@163.com")'); // 也是返回布尔类型值
      
    • 批量插入,返回 bool 类型

      <?php
      $db = DB::table('user');
      $data = [
        ['nickname' => 'xfjpeter', 'email' => 'fsyzxz@163.com'],
        ['nickname' => 'alice', 'email' => 'alice@163.com']
      ],
      $db->insert($data); // 返回布尔类型的值
      
  • insertGetId ,返回 插入的自增 id

    <?php
    $db = DB::table('user');
    $db->insertGetId(['nickname' => 'tom', 'email' => 'tom@163.com']);
    
2.2 删除
  • delete 返回受影响的行数

    • 配合 where 进行删除

      <?php
      DB::table('user')->where('id', 1)->delete();
      
    • 直接在 deleteid

      <?php
      DB::table('user')->delete(3);
      
  • truncate 清空整张表

    <?php
    DB::table('user')->truncate();
    
2.3 修改
  • update 返回受影响的行数

    <?php
    $db->where('nickname', '杨幂')->update(['nickname' => '刘诗诗']);
    
  • increment 自增操作,返回受影响的行数

    <?php
    $db->where('id', '100')->increment('vote', 5);
    
  • decrement 自减操作,返回受影响行数

    <?php
    $db->where('id', 1)->decrement(1);
    
2.4 查询
  • 取出基本数据

    • get 取出所有数据,返回的是一个 Collection

      <?php
      $res = DB::table('user')->where('id', 111)->get();
      dd($res->toArray());
      

      1、通过 foreach 循环时候,每一行的记录是一个 对象,不是数组

      2、如果查询没有结果,返回一个空 Collection

    • first 取出单行数据,返回一个对象

      <?php
      DB::table('user')->first();
      

      1、如果查询没有结果,返回 null

    • value 取出某个值

      <?php
      DB::table('user')->value('nickname');
      

      1、如果查询没有结果,返回 null

    • select 查询指定字段

      <?php
      DB::table('user')->select('nickname')->get();
      
    • select 执行 sql 语句,返回一个二维数据

      <?php
      DB::select("select * from user");
      
    • orderBy 按指定字段排序

      <?php
       DB::table('user')->orderBy('id', 'desc')->get();
      
    • limitoffset 配合进行分页操作

      <?php
      DB::table('user')->limit(3)->offset(0)->get();
      

五、本地和线上环境部署

1. 设置

  • 设置 php.ini 文件

    env="dev" ; 开发环境
    env="production" ; 生产环境
    
  • 设置 /bootstrap/app.php

    <?php
    // 新增一下内容
    $envs = ['dev', 'production'];
    $app->loadEnvironmentFrom('.env.' . get_cfg_var('env'));
    
  • 在根目录创建 .env.dev.env.production 分别表示开发和线上环境

六、视图操作

1. 文件位置

  • /resources/views

2. 文件命名方式

  • *.blade.php

    .php.blade.php 两个文件同时存在,.blade.php 会优先显示

3. 控制器视图渲染

3.1 控制器、视图、路由
  • 控制器:app/Http/Controllers/TestController.php

    <?php
      
    namespace App\Http\Controllers;
    
    class TestController
    {
        public function index()
        {
            return view('test.index');
        }
    }
    
    
  • 视图:resources/views/test/index.blade.php

    <h1>文件所在位置:resources/views/test/index.blade.php</h1>
    
  • 路由:routes/web.php

    <?php
    Route::get('test.index', 'TestController@index')->name('test.index');
    
3.2 控制器传参
  • view('视图文件', 参数数组)

    .
    .
    .
    return view('test.index', ['nickname' => 'xfjpeter', 'email' => 'fsyzxz@163.com']);
    .
    .
    .
    
  • with('键', '值') 传参

    return view('test.index')->with('nickname', 'xfjpeter')->with('email', 'fsyzxz@163.com');
    
  • with(数组) 传参

    return view('test.index')->with(['nickname' => 'xfjpeter', 'email' => 'fsyzxz@163.com']);
    

    模板中使用的时候,只能用数组的方式

3.3 标签
3.3.1 循环
  • @foreach

    @foreach($users as $key => $user)
        <div>key:{{$key}},昵称:{{$user->nickname}},邮箱:{{$user->email}}</div>
    @endforeach
    
3.3.2 判断语句
  • @if @elseif

    @foreach($users as $key => $user)
        @if($key % 2 == 0)
            <div style="color: red;">key:{{$key}},昵称:{{$user->nickname}},邮箱:{{$user->email}}</div>
        @else
            <div style="color: orange;">key:{{$key}},昵称:{{$user->nickname}},邮箱:{{$user->email}}</div>
        @endif
    @endforeach
    
3.4 模板继承
  • @yield('名称') 父级模板占位符
  • @extends('父级模板') 继承父级模板
  • @section 替换 yield 占位的内容区域
  • @include('文件名') 包含文件
3.5 引入资源文件
  • {{asset('css/app.css')}} 引入不带域名和版本号的 css 文件
  • {{mix('css/app.css')}} 引入带域名和版本号的 css 文件
3.6 引入 csrf
3.6.1 基本使用
  • {{csrf_token()}} 引入 csrf 码
  • {{csrf_field()}} 引入带 input 的csrf
  • 放在 meta 中,<meta name="csrf-token" content="{{ csrf_token() }}">
3.6.2 排除不需要验证的路由
  • 路径:app/Http/Middleware/VerifyCsrfToken.php$except 中填写

七、validate 验证器

1. 基本使用

  • required 必填项

    $this->validate($request, [
      'name' => 'required'
    ], [
      'name.required' => '姓名不能为空'
    ])
    
  • unique 表字段唯一

    $this->validate($request, [
      'name' => 'required|unique:users,name'
    ], [
      'name.unique' => '姓名已经存在'
    ])
    
  • regex 正则验证

    $this->validate($request, [
      'name' => 'required|regex:\w{4,16}'
    ])
    

其他

1、添加自定义文件,如 bootstrap/helpers.php

  1. 创建文件 helpers.php

  2. 在文件中写入以下内容

    <?php
    function test_helper()
    {
        return 'OK';
    }
    
    
  3. composer.json 中写入以下内容

    {
      ...
      "autoload": {
        "files": [
          "bootstrap/helpers.php"
        ]
      }
    }
    
  4. 在命令行执行 composer dumpautoload

  5. 测试文件是否导入成功,执行下面命令后输出 OK 表示导入成功

    $ php artisan tinker
    >>>test_helper()
    

2、引入 bootstrap vue

  1. 引入 laravel/ui 包,composer require laravel/ui:"^1.0" --dev
  2. 上一步之行成功,引入 bootstrap,php artisan ui vue
  3. npm install 安装依赖模块
  4. 监视文件变化,npm run watch-poll,如果这一步执行错误,可能是 sass-loader 版本号太高,卸载 sass-loader 重新安装一下:npm install --save-dev sass-loader@7.1.0

3、工厂类的使用

  1. 使用命令创建一个 factory 和 migration ,php artisan make:model UserAddress -fm

  2. 在生成的 database/migrations 下找到刚刚创建的表类,写入以下内容

    ...
    public function up()
    {
      Schema::create('user_addresses', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedBigInteger('user_id');
        $table->foreign('user_id')->on('users')->references('id')->onDelete('cascade');
        $table->string('province');
        $table->string('city');
        $table->string('district');
        $table->string('address');
        $table->unsignedInteger('zip');
        $table->string('concat_name');
        $table->string('concat_phone');
        $table->dateTime('last_used_at')->nullable();
        $table->timestamps();
      });
    }
    ...
    
    
  3. 使用迁移命令,生成表,php artisan migrate

  4. database/factories/UserAddressFactory 中书写以下内容

    <?php
    
    /** @var \Illuminate\Database\Eloquent\Factory $factory */
    
    use App\Models\UserAddress;
    use Faker\Generator as Faker;
    
    $factory->define(UserAddress::class, function (Faker $faker) {
        $addresses = [
            ["北京市", "市辖区", "东城区"],
            ["河北省", "石家庄市", "长安区"],
            ["江苏省", "南京市", "浦口区"],
            ["江苏省", "苏州市", "相城区"],
            ["广东省", "深圳市", "福田区"],
        ];
        $address   = $faker->randomElement($addresses);
        return [
            'province'     => $address[0],
            'city'         => $addresses[1],
            'district'     => $address[2],
            'address'      => sprintf('第%d条街道第%d号', $faker->randomNumber(2), $faker->randomNumber(3)),
            'zip'          => $faker->postcode,
            'concat_name'  => $faker->name,
            'concat_phone' => $faker->phoneNumber,
        ];
    });
    
    
    • $faker->randomElement($addresses) 是从 $addresses 中随机出一个元素
    • $faker->randomNumber() 是随机生成指定位数的数字
    • $faker->postcode 是随机获取邮编号码
    • $faker->name 随机生成用户姓名
    • $faker->phoneNumber 随机生成手机号码
  5. 测试刚刚创建的工厂文件

    $ php artisan tinker
    >>> factory(App\Models\UserAddress::class)->make()
    
    • factory()->make() 只是生成了数据,并未保存到数据库中,保存数据需要用到 create 命令

      >>> factory(App\Models\UserAddress::class, 3)->create(['user_id' => 1])
      

4、使用 policy 控制权限

  1. 创建一个 policyphp artisan make:policy UserAddressPolicy

  2. 在创建的文件中新增以下内容

    public function own(User $user, UserAddress $address)
    {
        return $address->user_id == $user->id;
    }
    
  3. 接下来需要在 AuthServiceProvider 注册这个授权策略,app/Providers/AuthServiceProvider.php,写入以下内容

    public function boot()
    {
      $this->registerPolicies();
    
      // 使用 Gate::guessPolicyNamesUsing 方法来自定义策略文件的寻找逻辑
      Gate::guessPolicyNamesUsing(function ($class) {
        // class_basename 是 Laravel 提供的一个辅助函数,可以获取类的简短名称
        // 例如传入 \App\Models\User 会返回 User
        return '\\App\\Policies\\'.class_basename($class).'Policy';
      });
    }
    
  4. 在控制器中使用,例如以下代码

    class UserAddressesController
    {
      public function edit(UserAddress $userAddress)
      {
        // 以下这行代码是触发策略机制
        $this->authorize('own', $userAddress);
      }
    }
    

5、seeder 的使用

  1. 先创建 factory

  2. 使用命令创建 seeder 文件,php artisan make:seeder ProductsSeeder

  3. 在创建的文件中写入代码,如:

    public function run()
    {
      $products = factory(\App\Models\Product::class, 30)->create();
      foreach ($products as $product) {
        // 创建 3 个 sku
        $skus = factory(\App\Models\ProductSku::class, 3)->create(['product_id' => $product->id]);
        // 找出最低的价格
        $product->update(['price' => $skus->min('price')]);
      }
    }
    
  4. 执行,php artisan db:seed --class=ProductsSeeder

6、Exception 的使用

6.1 用户错误行为触发的异常
  1. 创建一个 exception 类,php artisan make:exception InvalidRequestException

  2. 在刚刚创建的 InvalidRequestException 中写入以下内容

    <?php
    
    namespace App\Exceptions;
    
    use Exception;
    use Illuminate\Http\Request;
    
    class InvalidRequestException extends Exception
    {
        public function __construct(string $message = "", int $code = 400)
        {
            parent::__construct($message, $code);
        }
    
        public function render(Request $request)
        {
            if ($request->expectsJson()) {
                // json() 方法第二个参数就是 Http 返回码
                return response()->json(['msg' => $this->message], $this->code);
            }
    
            return view('pages.error', ['msg' => $this->message]);
        }
    }
    
    • $request->expectsJson() 判断当前是否 ajax 请求,如果是返回 json 格式的数据,否则在页面在返回错误信息
  3. 创建 resource/views/pages/error.blade.php 文件,写入以下内容

    @extends('layouts.app')
    @section('title', '错误')
    
    @section('content')
    <div class="card">
        <div class="card-header">错误</div>
        <div class="card-body text-center">
            <h1>{{ $msg }}</h1>
            <a class="btn btn-primary" href="{{ route('root') }}">返回首页</a>
        </div>
    </div>
    @endsection
    
  4. 如果不期望把这个日志写入栈内,在 app/Exceptions/Handler.php 文件中,把刚刚创建的类,写入进入

    protected $dontReport = [
      InvalidRequestException::class,
    ];
    
6.2 创建系统内部异常,开发者须知
  1. 先创建异常类,php artisan make:exception InternalException

  2. app/Exceptions/InternalException 中写入

    <?php
    
    namespace App\Exceptions;
    
    use Exception;
    use Illuminate\Http\Request;
    
    class InternalException extends Exception
    {
        protected $msgForUser;
    
        public function __construct(string $message, string $msgForUser = '系统内部错误', int $code = 500)
        {
            parent::__construct($message, $code);
            $this->msgForUser = $msgForUser;
        }
    
        public function render(Request $request)
        {
            if ($request->expectsJson()) {
                return response()->json(['msg' => $this->msgForUser], $this->code);
            }
    
            return view('pages.error', ['msg' => $this->msgForUser]);
        }
    }
    
  3. 使用,在需要抛出异常的地方

    ...
    throw new InvalidRequestException('这是抛出的异常提示信息');
    ...
    

7、任务队列的使用

  1. 创建一个任务队列,php artisan make:job OrderClose

  2. 在刚刚创建的类中写入:

    <?php
    
    namespace App\Jobs;
    
    use Illuminate\Bus\Queueable;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    use Illuminate\Foundation\Bus\Dispatchable;
    use App\Models\Order;
    
    // 代表这个类需要被放到队列中执行,而不是触发时立即执行
    class CloseOrder implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
        protected $order;
    
        public function __construct(Order $order, $delay)
        {
            $this->order = $order;
            // 设置延迟的时间,delay() 方法的参数代表多少秒之后执行
            $this->delay($delay);
        }
    
        // 定义这个任务类具体的执行逻辑
        // 当队列处理器从队列中取出任务时,会调用 handle() 方法
        public function handle()
        {
            // 判断对应的订单是否已经被支付
            // 如果已经支付则不需要关闭订单,直接退出
            if ($this->order->paid_at) {
                return;
            }
            // 通过事务执行 sql
            \DB::transaction(function() {
                // 将订单的 closed 字段标记为 true,即关闭订单
                $this->order->update(['closed' => true]);
                // 循环遍历订单中的商品 SKU,将订单中的数量加回到 SKU 的库存中去
                foreach ($this->order->items as $item) {
                    $item->productSku->addStock($item->amount);
                }
            });
        }
    }
    
  3. 触发任务

    use App\Jobs\CloseOrder;
        .
        .
        .
        public function store(OrderRequest $request)
        {
            .
            .
            .
            $this->dispatch(new CloseOrder($order, config('app.order_ttl')));
            // 也可以使用函数:dispatch(new CloseOrder($order, config('app.order_ttl')))
    
            return $order;
        }
    
  4. 启动任务队列,php artisan queue:work

写在最后,持续更新中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潇洒哥GG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值