Skip to content

约 3470 字大约 12 分钟

2026-07-06

概念

回调函数

回调函数的作用是将一个函数作为参数传递给另一个函数, 当这个函数执行完毕后, 会调用这个回调函数, 并将结果传递给回调函数

function myFunction(param1, param2, callback) {
  const result = param1 + param2

  callback(result)
}

myFunction(1, 2, (result) => {
  console.log(`回调函数被调用,结果为:${result}`)
})

类中的静态方法

如果想要调用一个类中的函数,需要先将类实例化才能够调用类中的函数

class MyClass {
    public function myMethod() {
        return "这是一个普通方法";
    }
}

$myObject = new MyClass();
echo $myObject->myMethod(); // 输出: 这是一个普通方法

如果想要直接调用类中的函数而不需要实例化这个类,那么就需要将这个函数定义为静态方法

class MyClass {
    public static function myStaticMethod() {
        return "这是一个静态方法";
    }
}

echo MyClass::myStaticMethod(); // 输出: 这是一个静态方法

laravel

路由

提示

在 laravel11 之后的版本需要执行命令

php artisan install:api

才能在在 /routes/api.php 中定义接口, 否则会没有这个文件

常用路由

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

一般直接绑定控制器即可,不需要使用回调函数

Route::get('/', [UserController::class, 'show']);

特殊路由

Route::match(['get', 'post'], '/', function () {
    // ...
});

Route::any('/', function () {
    // ...
});

//                                 第三个参数可以设置状态码,默认是 302
Route::redirect('/here', '/there', 301);

//                                 第三个参数是传给视图的参数
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

提示

路由的定义也有顺序关系

比如我们需要在 / 下定义一个 any 路由和一个 post 路由

如果你先定义了 any 路由,那么所有的请求都会被 any 路由匹配到,post 路由将永远不会被匹配到。

路由参数

Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});

在控制器里也是一样的

/route/api.php
Route::get('user/{id}', [UserController::class, 'show']);
/app/Http/Controllers/UserController.php
class UserController extends Controller
{
    public function show(Request $request, $id)
    {
        return 'User '.$id;
    }
}

路由参数的值有时候是可选的, 在参数的结尾加上 ? 就可以了, 但是在后面的处理函数里要给参数一个默认值

Route::get('user/{name?}', function ($name = null) {
    return $name;
});

分组

分组一般配合 prefix、middleware 等使用

prefix 是路由前缀,比如原本的路由是 /users,加上 prefix('admin') 后就变成了 /admin/users

middleware 是中间件,所有的路由都会经过中间件的处理

Route::prefix('admin')->group(function () {
    Route::get('users', function () {});
});

// 此处也可以直接导入中间件的类
Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {});
});

中间件

提示

创建中间件请使用 php artisan make:middleware 命令

一般在路由中使用中间件需要先在 /bootstrap/app.php 中注册

然后再到你的路由中去使用

/app/Http/Middleware/Auth2.php
<?php

namespace App\Http\Middleware;

use App\Http\Controllers\ResponseController;
use App\Models\User;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\Response;

class Auth2
{
    /**
     * Handle an incoming request.
     *
     * @param  Closure(Request): (Response)  $next
     */
    //                      请求参数          是否继续参数    中间件参数,他是从路由中传递过来的
    public function handle(Request $request, Closure $next, $type="ADMIN|WORKER|USER", $statusCode=422): Response
    {
        //校验是否携带token字段
        $validated=Validator::make($request->query(),[
           'token'=>'required'
        ]);
        if($validated->fails()){
            return ResponseController::failure($statusCode);
        }

        //判断用户角色
        $type=explode('|',$type); //把$type按|拆成数组
        $user=User::query()->firstWhere('token',$request['token']);
        if(!$user){
            return ResponseController::failure(404,'not found');
        }
        if(!in_array($user['type'],$type)){
            return ResponseController::failure(401,'unauthorized access');
        }

        // 如果不调用这个 $next($request) 函数,那么这个中间件就不会继续执行下去,也就不会进入到路由中定义的回调函数中
        return $next($request);
    }
}

迁移

创建迁移

这里的 create_xxxx_table 是固定的格式,中间的 xxxx 是你要创建的表名,必须是复数形式。

php artisan migrate:make create_users_table

运行迁移

php artisan migrate

如果迁移存在破坏性

php artisan migrate --force

如果想要完全重新执行一次迁移,这会删除现在的所有表,然后重新开始执行迁移

php artisan migrate:refresh --force

如果迁移还需要同步执行 seeder ,那么需要带上 --seed 参数

php artisan migrate:refresh --seed --force

seeder

seeder 是用来给数据库表插入测试数据的,但是我们也可以用来创建默认数据使用

默认的 seeder 文件在 /database/seeders/DatabaseSeeder.php

<?php

namespace Database\Seeders;

use App\Models\Table;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    use WithoutModelEvents;

    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        User::query()->create([
            "username" => "admin",
            "password" => md5("adminpass"),
            'type' => 'ADMIN',
            'token' => ''
        ]);

        User::query()->create([
            "username" => "user",
            "password" => md5("userpass"),
            'type' => 'USER',
            'token' => ''
        ]);

        User::query()->create([
            "username" => "worker",
            "password" => md5("workerpass"),
            'type' => 'WORKER',
            'token' => ''
        ]);

        for ($i = 1; $i <= 3; $i++) {
            Table::query()->create([
                "table_type" => "A",
                "status" => "UNOCCUPIED"
            ]);
        }

        for ($i = 1; $i <= 3; $i++) {
            Table::query()->create([
                "table_type" => "B",
                "status" => "UNOCCUPIED"
            ]);
        }

        for ($i = 1; $i <= 3; $i++) {
            Table::query()->create([
                "table_type" => "C",
                "status" => "UNOCCUPIED"
            ]);
        }
    }
}

CSRF

你只需要记住,这个东西只有在你把接口定义在了 /routes/web.php 里才会生效,如果你把接口定义在了 /routes/api.php 里,那么 CSRF 就不会生效。

然后一般是这样用的, 在 blade 模板里使用 @csrf 指令就可以了,不然的话你会收到一个 419 的错误,表示 CSRF 验证失败。

<form method="POST" action="/profile">
    @csrf
    ...
</form>

blade模板

插值语法

中间的 $name 是一个变量, 如果你需要输出一个在变量中的 HTML 代码, 那么你需要使用 {!! $name !!} 来输出, 否则的话会被转义成普通文本

{{ $name }}

{!! $name !!}

控制语法

@if(condition)
    // 条件为 true 时执行的代码
@elseif(condition)
    // 条件为 true 时执行的代码
@else
    // 条件为 false 时执行的代码
@endif

循环语法

@foreach($users as $user)
    // 循环体
@endforeach

@for ($i = 0; $i < 10; $i++)
    // 循环体
@endfor

@while (condition)
    // 循环体

    // 正常的continue和break语法也是在所有循环中可用的
    @continue
    @break
@endwhile

样式语法

@php
    $isActive = false;
    $hasError = true;
@endphp

//    这里表示如果 $isActive 为 true,则添加 font-bold 类,否则添加 text-gray-500 类
//    如果 $hasError 为 true,则添加 bg-red 类
<span @class([
    'p-4',
    'font-bold' => $isActive,
    'text-gray-500' => ! $isActive,
    'bg-red' => $hasError,
])></span>

<span class="p-4 text-gray-500 bg-red"></span>

//    这里表示如果 $isActive 为 true,则添加 font-weight: bold 样式,否则不添加
<span @style([
    'background-color: red',
    'font-weight: bold' => $isActive,
])></span>

标签语法

常用的一些 html 属性也有对应的命令, 可以省去一些自己去写 if 的麻烦, 例如 checked、selected、disabled、readonly、required

<input
    type="checkbox"
    name="active"
    value="active"
    @checked(true)
/>


<select name="version">
    <option value="aa" @selected(false)>
        aaa
    </option>
</select>

<button type="submit" @disabled(true)>Submit</button>

<input
    type="email"
    name="email"
    value="email@laravel.com"
    @readonly(false)
/>

<input
    type="text"
    name="title"
    value="title"
    @required(true)
/>

控制器

php artisan make:controller

在类中新建函数, 函数必须使用 public 修饰符

过滤器

关于导入

所有可用规则: https://www.laravel.wiki/validation#%E5%8F%AF%E7%94%A8%E9%AA%8C%E8%AF%81%E8%A7%84%E5%88%99

$validator = Validator::make($request->post(), [
    "name" => "required|string|max:255",
    "email" => "required|email|unique:users",
    "password" => "required|string|min:6|confirmed",
    // confirmed规则默认会去验证password_confirmation字段, 如果你想要验证其他字段, 那么就需要使用same规则来验证
    // password也就是当前字段的名称, 比如密码字段叫aaa, 那么验证的字段就是 aaa_confirmation
    // "password_confirmation" => "required|string|same:password"
]);

// 不过这里的一些过滤规则只能和laravel自带的blade配合使用,我们可以让他更加通用一些
if ($validator->fails()) {}
class ExampleController extends Controller
{
    public function register(Request $request)
    {
        $validator = Validator::make($request->post(), [
            "name" => "required|string|max:255",
            "email" => "required|email|unique:users",
            "password" => "required|string|min:6|confirmed",
            // confirmed规则默认会去验证password_confirmation字段, 如果你想要验证其他字段, 那么就需要使用same规则来验证
            // password也就是当前字段的名称, 比如密码字段叫aaa, 那么验证的字段就是 aaa_confirmation
            // "password_confirmation" => "required|string|same:password"
        ]);

        // 不过这里的一些过滤规则只能和laravel自带的blade配合使用,我们可以让他更加通用一些
        if ($validator->fails()) {
            // 判断哪个规则被触发了
            $failed = $validator->failed();

            // 判断是不是email的unique规则被触发了
            // 这里的 Unique 是规则的名称, 不是字段的名称
            // 并且首字母需要大写, 比如 min:6 规则触发了, 那么这里就是 $failed["password"]["Min"] 这个属性存在, 也就是 Min 首字母大写
            if (isset($failed["email"]["Unique"])) {
                return response()->json([
                    "success" => false,
                    "message" => "邮箱已经被注册了"
                ],422);
            }

            return response()->json([
                "success" => false,
                "message" => "参数验证失败"
            ], 422);
        }

        // 如果验证通过, 那么就可以进行注册了
    }
}

集合

所有可用方法: https://www.laravel.wiki/collections#%E5%8F%AF%E7%94%A8%E6%96%B9%E6%B3%95

$collection = collect([1, 2, 3]);
$collection->all(); // [1, 2, 3]
$collection->avg(); // 2
$collection->chunk(2); // [[1, 2], [3]]
$collection->map(function ($item, $key) {
    return $item * 2;
}); // [2, 4, 6]
$collection->filter(function ($item, $key) {
    return $item > 2;
}); // [3]

辅助函数

最常用的就是调试命令

dd($var); // 打印变量并终止程序
dump($var); // 打印变量但不终止程序

可用辅助函数: https://www.laravel.wiki/helpers#%E5%85%B6%E4%BB%96

只要看这个其他就够了

模型

php artisan make:model

在 model 中有几个常用属性

class User extends Model
{
    // 在插入用户的时候需要将插入的字段添加到这个属性中
    // 比如我们在调用 create 函数的时候, 传入的字段如果不在这个 $fillable 中, 那么他就不会被添加到操作数据库的sql语句中
    protected $fillable = [
        "name",
        "email",
        "password",
        "token"
    ];

    // 这里定义的属性会在序列化的时候去除
    // 比如我们通过 get 函数获取到了这个User模型, 我们直接把他放到 response->json($user) 中, 那么返回的json中就不会有token和password字段了
    protected $hidden = [
        "token",
        "password"
    ];

    // 关闭在调用 create 函数的时候添加的 created_at 和 updated_at 字段, 也就是关闭时间戳
    public $timestamps = false;
}

在控制器或其他部分使用模型

在调用模型之前需要先调用 query 函数后,才能够获得正常的提词器。 还有一些常用的附属函数:https://www.laravel.wiki/eloquent

User::query()->create([
    "name" => $request->post("name"),
    "email" => $request->post("email"),
    "password" => Hash::make($request->post("password")),
    "token" => Str::uuid()->toString()
]);

获取所有数据

$users = User::query()->get();

查询条件

// 查询年龄大于18岁的用户
$users = User::query()->where('age', '>', 18)->get();

// 查询年龄大于18岁且名字是John的用户
$users = User::query()->where('age', '>', 18)->where('name', '=', 'John')->get();
// 简化写法
$users = User::query()->where([
  "age" => 18,
  "name" => "John"
])->get();

// 也支持高级数组写法
$users = User::query()->where([
  ["age", ">", 18],
  ["name", "=", "John"]
])->get();

// 查询年龄大于18岁或名字包含John的用户
$users = User::query()->where('age', '>', 18)->orWhere('name', 'like', '%John%')->get();

// 查询id在1,2,3之间的用户
$users = User::query()->whereIn('id', [1, 2, 3])->get();

获取条目数量

$count = User::query()->where('age', '>', 18)->count();

更新数据

User::query()->where('id', 1)->update(['name' => 'New Name']);

删除数据

User::query()->where('id', 1)->delete();

新建数据

User::query()->create([
    'name' => 'John Doe',
    'email' => 'john.doe@example.com',
    'password' => bcrypt('password'),
]);

高级用法

关联查询

Str类

关于导入

// 生成一个uuid, 并把他转换成字符串类型
$token = Str::uuid()->toString();

关于导入

一般导入的辅助类 Validator Request Str Random 等等

都优先使用 Illuminate\Support\Facades 下的

如果没有就使用 Illuminate\Support 下的

关于路由

提示

此处的路由指的是 web.php 中的路由, 不是 api.php 中的路由

在 laravel 中的路由分为两种,一种是我们在 /routes 中定义的路由,另一种就是我们在 /public 下放置的静态资源文件

在 /routes 中定义的路由一般表示需要经过 laravel 的处理,才能够返回给前端的路由

在 /public 下放置的静态资源文件一般表示不需要经过 laravel 的处理,直接返回给前端的路由

在什么情况下需要经过 laravel 的处理呢?

比如你使用了 blade 模板引擎(就是放置在 /resources/views 下的模板文件,我们称为 blade 模板),那么你在 /routes 中定义的路由就需要经过 laravel 的处理,才能够返回给前端

一般情况下,如果你的项目是一个前后端分离的项目,那么你就不会去使用 blade 模板引擎,也就直接放置在 /public 下的静态资源文件就可以了,不需要经过 laravel 的处理

js

网络请求

Fetch MDN文档

使用 fetch 函数

在使用 fetch 与 laravel 后端进行网络请求的时候需要手动携带上 头部信息

await fetch('/api', {
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  },
})

如果 fetch 函数在里另一个函数里, 那么这个函数需要加上 async 修饰符, 并且在调用这个函数的时候需要加上 await 修饰符

比如:

async function getData() {
  await fetch('/api', {
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
  })
}

button.addEventListener('click', async () => {
  await getData()
})

路由参数解析

对于路由参数的提取通常会比较麻烦, 我们可以使用 URLSearchParams 来解析路由参数, 这个类可以将路由参数解析成一个对象, 然后我们就可以通过对象的属性来获取路由参数的值

const urlParams = new URLSearchParams(window.location.search)
const id = urlParams.get('id')