在创建 Laravel 项目之前,要先在本地机器上安装 PHP 和 Composer。Composer 是用来管理 PHP 依赖关系的工具,相当于 Node.js 的 npm 。
安装 PHP 和 Composer 后,可以通过 create-project 命令创建一个新的 Laravel 项目:
composer create-project laravel/laravel example-app
当应用程序创建完成后,可以通过 Artisan CLI 的 serve 命令来启动 Laravel 的本地服务:
cd example-app
php artisan serve
Laravel 的配置选项值在 .env 文件中定义,可以使用 env() 函数来获取配置值。
php artisan make:command
命令创建php artisan make:controller
php artisan make:middleware
php artisan make:model
use Illuminate\Support\Facades\Route;
// prefix:路由前缀
// namespace:该路由所属控制器的命名空间
// middleware:中间件,要求以下接口登录后才能请求
// group:路由组
Route::prefix('app')->namespace('App')->middleware('login')->group(function () {
Route::get('/', 'HomeController@index');
Route::prefix('book')->group(function () {
Route::get('/list', 'BookController@list');
Route::get('/{id}', 'BookController@show')->where('id', '[0-9]+'); // 对路由参数进行正则表达式约束
});
Route::post('/user/login', 'UserController@login');
});
Laravel 通过中间件来检查和过滤进入应用程序的 HTTP 请求。如中间件 login,用于验证用户是否已经登录。如果用户未登录,中间件会将用户重定向到登录页面,如果用户已登录,中间件才允许请求进一步进入应用程序。
namespace App\Http\Middleware;
use Closure;
class CheckUserLogin
{
// 在应用程序处理请求之前执行
public function handle($request, Closure $next)
{
if ($request->isLogin == 0) {
return redirect('login');
}
return $next($request);
}
}
可以使用 make:middleware CheckUserLogin
Artisan 命令在 app/Http/Middleware 目录中创建新的中间件。在 Kernel.php 中的 $routeMiddleware 中配置中间件的别名 'login' => \App\Http\Middleware\CheckUserLogin::class,
使用make:controller BookController
命令在 app/Http/Controllers 目录下新建 controller,用来处理应用程序请求和响应的逻辑。
namespace App\Http\Controllers\App;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request; // 封装了当前请求的所有相关数据
use Illuminate\Http\JsonResponse; // Laravel中用于生成JSON格式的HTTP响应的类
class BookController extends Controller
{
public function show(Request $request, $bid): JsonResponse
{
// ...
return response()->json($data); // 返回json
}
public function list(Request $request)
{
// ...
return view('books', $data); // 返回视图
}
}
Request 类的常用方法
$request->isMethod('post')
检查当前请求是否为指定的 HTTP 方法,返回 bool 值。$request->get('age', 18);
获取请求参数中指定键的值,可设置默认值。$request->validate([]);
表单验证,验证的规则主要有字段必填(required)、字段类型(string / numeric / email / url )、字段的值必须在给定的列表中(in:1,2)、字段的值于另一字段的值一致(same:password 验证再次输入密码)$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8',
'age' => '',
]);
$request->file('photo')->isValid()
检查上传文件是否有效。Blade 模板文件使用 .blade.php 作为文件扩展名,被存放在 resources/views 目录。
Blade 视图使用全局 view() 函数从控制器返回。
Blade 通过 @yield 和 @session 命令来继承布局。
首先定义一个主页面布局,@yield 指令用来显示指定部分的内容:
<html>
<head>
<title>App Name - @yield('title')title>
head>
<body>
<header>
header>
<main>
@yield('content')
main>
<footer>
footer>
body>
html>
然后定义一个继承此布局的子页面,@extends 指令指定子页面要继承的视图,使用 @section 指令向布局片段注入内容:
<!-- 位于 resources/views/child.blade.php -->
@extends('layouts.app')
@section('title', 'Page Title')
@section('content')
<p>This is my body content.</p>
@endsection
{{ $name }}
中在视图中展示数据{{!! $name !!}}
语法。@verbatim
<div>{{ name }}div>
@endverbatim
@if ... @elseif ... @else ... @endif
@foreach($items as $item) ... @endforeach
,循环内部可以使用 @loop 变量来获取当前循环的迭代信息。{{-- 注释内容不会返回到 HTML --}}
@include('header')
Laravel 中,可以使用原生 SQL,查询构造器,以及 Eloquent ORM 等方式与数据库交互。
Laravel 数据库服务的配置位于 config/database.php 配置文件中。
在 Laravel 中,可以通过 DB Facade 来执行原生 SQL,DB Facade 为每种类型的操作都提供了对应的方法,如:insert、select、update、delete 等。
use Illuminate\Support\Facades\DB;
$users = DB::select('select * from users where id = ?', [1]);
除了使用 ?
表示参数绑定外,你还可以使用命名绑定的形式来执行一个查询:
$users = DB::select('select * from users where id = :id', ['id' => 1]);
select 方法将始终返回一个包含查询结果的数组。数组中的每个结果都对应一个数据库记录的 stdClass 对象:
foreach ($users as $user) {
echo $user->name;
}
Laravel 可以使用 DB facade 里的 table 方法来开始查询。table 方法为给定的表返回一个查询构造器实例,允许在查询上链式调用更多的约束,最后使用 get 方法获取结果。
$users = DB::table('users')->where('id', 1)->get();
foreach ($users as $user) {
echo $user->name;
}
get 方法返回一个包含 Illuminate\Support\Collection 的结果,其中每个结果都是 PHP StdClass 对象的一个实例。
如果只需要从数据表中获取一行数据,你可以使用 first 方法。该方法返回一个 StdClass 对象:
$users = DB::table('users')->where('id', 1)->first();
echo $user->name;
Collection 集合
查询构造器具体查询的语法可以和 Sql 语句对比学习:
use Illuminate\Support\Facades\DB;
$users = DB::table('users')
->select(['users.id', 'users.name', 'orders.order_number'])
->join('orders', 'users.id', '=', 'orders.user_id') // join(inner join) / leftJoin
->where('users.status', 'active')
->orWhere('users.status', 'pending')
->groupBy(['users.id'])
->having('user_count', '>', 5)
->whereBetween('orders.total_amount', [1000, 5000])
->orderBy('users.created_at', 'desc') // 也可以使用 orderByDesc('users.created_at')
->offset(5)
->limit(10) // 也可以使用 ->skip(5)->take(10)
->get();
SELECT users.id, users.name, orders.order_number
FROM users
JOIN orders ON users.id = orders.user_id
WHERE (users.status = 'active'
OR users.status = 'pending')
AND orders.total_amount BETWEEN 1000 AND 5000
GROUP BY users.id
HAVING user_count > 5
ORDER BY users.created_at DESC
LIMIT 5, 10;
查询构造器可以通过 paginate 方法对结果进行分页。
控制器逻辑:
$users = User::paginate(10); // 每页显示10条记录
return view('users.index', compact('users')); // compact('users') 相当于 ['users' => $users]
视图文件:
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
@foreach ($users as $user)
<tr>
<td>{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
</tr>
@endforeach
</table>
{{ $users->links() }} <!-- 显示分页链接 -->
在 laravel 中,可以通过调用 Redis facade 上的各种方法来与 Redis 进行交互。
use Illuminate\Support\Facades\Redis;
if(Redis::exists($key)){
$result = Redis::get($key);
} else {
Redis::setex($key, 300, $data);
}
Laravel 的 Eloquent 模块,是一个对象关系映射 (ORM:Object-Relational Mapping)。在使用 Eloquent 时,数据库中每张表都有一个相对应的” 模型” 用于操作这张表。
通过 php artisan make:model User
命令生成模型类,生成的模型会被放置在 app/Models 目录下。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
protected $table = 'users'; // 数据表名
protected $primaryKey = 'id'; // 主键,默认为id是可以不设置
public $timestamps = false; // 是否自动维护时间戳,true时创建或更新数据会自动维护created_at和updated_at字段
public $fillable = [ // 只有在该数组中列出的字段才能通过 create() 或 fill() 方法进行批量赋值
'name',
'age',
];
// ...
use SoftDeletes; // 启用软删除,在数据表中添加deleted_at字段
}
一旦你创建了一个模型和 其关联的数据库表,可以将每个 Eloquent 模型视为一个强大的查询构建器。所以说查询构造器中的方法,在 Eloquent 中是通用的,只需要将 DB::table('users')
替换为User
即可。
use App\Models\User;
$user = User::create([
'name' => 'Alice',
]);
use App\Models\User;
$user = new User;
$user->name = 'Alice';
$user->save();
use App\Models\User;
$data = [
[ 'name' => 'Alice','age' => 18],
[ 'name' => 'John', 'age' => 20],
];
User::insert($data);
use App\Models\User;
$user = User::where('id', 1);
$user->age = 18;
$user->save();
use App\Models\User;
User::where('age', '>', 0)
->update(['sex' => 1]);
use App\Models\User;
User::where('name', 'Alice')->delete();
use Illuminate\Support\Facades\DB;
$result = User::query()
->select([DB::raw('count(*) as user_count')])
->where('status', 1)
->get();
User::where('id', $id)->decrement('money', n);
n 没有传入时默认为1User::where('age', 18)->count();
https://learnku.com/docs/laravel/10.x/eloquent-relationships/14889#e05dce
数据表之间通常相互关联,除了查询构造器使用 JOIN 关联数据表之外,Eloquent 还提供了多种关联类型,使关联的管理和使用更加简单。
默认情况下,Eloquent 会自动按照约定为模型类设置外键和主键。
例如:一个 User 模型可能与一个 Phone 模型相关联
首先,在 User 模型中定义一个 phone 方法,在 phone 方法中调用 hasOne
方法并返回结果:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class User extends Model
{
/**
* 获取与用户相关的电话记录
*/
public function phone(): HasOne
{
return $this->hasOne(Phone::class, 'user_id', 'id');
// 后两个参数分别为关联模型 Phone 模型的外键,和父模型 User 模型的主键,和默认情况一致时可以省略
}
}
一旦定义了模型关联,就可以通过 $phone = User::find(1)->phone;
来获取相关数据。
目前已经能从 User 模型访问到 Phone 模型了,要想从 Phone 模型访问到 User 模型,需要在 Phone 模型中调用 belongsTo
方法来定义反向关联。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Phone extends Model
{
/**
* 获取与用户相关的电话记录
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id', 'id');
// 后两个参数分别为关联模型 Phone 模型的外键,和父模型 User 模型的主键,和默认情况一致时可以省略
}
}
例如,一篇博客(Post 模型)可以有很多条评论(Comment 模型)
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Post extends Model
{
/**
* 获取这篇博客的所有评论
*/
public function comments(): HasMany
{
return $this->hasMany(Comment::class, 'post_id', 'id');
}
}
在 Post 中定义 comments 方法,调用 hasMany 来获取评论集合
use App\Models\Post;
$comments = Post::find(1)->comments;
foreach ($comments as $comment) {
// ...
}
同样,也可以在 Comment 模型中定义 post 方法,调用 belongsTo 方法来反向获取评论对应的博客信息。
例如,一个用户可以有多个角色,同时这些角色也可以分配给其他用户。
要定义这个关联,需要三个数据表:users、roles、role_user。其中,role_user 包括 user_id 和 role_id 字段,用来链接 users 和 roles 表。
在 User 模型中定义 roles 方法,调用 belongsToMany 方法获取用户所有的角色:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class User extends Model
{
/**
* 用户所拥有的角色
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(
Role::class,
'role_user', // 中间表名
'user_id', // 定义此关联的模型(User)在中间表的外键名
'role_id' // 另一模型(Role)在中间表的外键名
);
}
}
同样,也可以在 Role 模型中调用 belongsToMany 方法获取某个角色的全部用户。
由于处理多对多关系需要一个中间表,Eloquent 也提供了方法和中间表进行交互。例如,通过模型关联获取的每个 Role 模型对象,都会被自动赋予 pivot
属性,它代表中间表的一个模型对象,并且可以像其他的 Eloquent 模型一样使用。
use App\Models\User;
$user = User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at; // 这里的created_at是中间表role_user的字段
}