Laravel+API 接口
网课连接:BIlibili.
中文文档.
1.RestFul Api编码风格
一、API设计
-
修改hosts,
C:\Windows\System32\drivers\etc\hosts
,增加127.0.0.1 api.lv8.com # Laravel 框架
用这个域名来测试(推荐规范) -
在命令行中使用
php artisan serve --host api.lv8.com
-
在
.env
和config/database.php
中配置mysql数据库等服务用的wamp;注意这里的
database.php
需要配置 prefix属性php'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => 'laravel_', # 重点 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ],
-
安装Postman,测试接口,
https://cdn.liyanhui.com/data.json
二、RestFul
-
RestFul Api
是一种设计风格,推荐的一种规范,有助于统一协同和管理; -
这里提供两个网址
2.资源控制器和路由
一、资源控制器
- 创建一个API-Controller
php artisan make:controller UserController --api
二、资源路由
-
创建好 API 资源控制器之后,在
route/web.php
配置相关api资源路由;Route::apiResourcce('users', 'UserController');
HTTP类型 | 路由URI | 控制器方法 | 路由命名 | 描述 |
---|---|---|---|---|
GET | users | index() | users.index | 获取数据列表 |
POST | users | store() | users.store | 创建页的接受处理 |
GET | users/{user} | show() | users.show | 获得一条数据 |
PUT/PATCH | users/{user} | update() | users.update | 从编辑页中接受处理 |
DELETE | users/{user} | destroy() | users.destroy | 删除一条数据 |
PS:可以通过
php artisan route:list
来查看资源路由列表
3.安装Laravel8.x
-
使用
composer
创建composer create-project --prefer-dist laravel/laravel blog
-
提前配置好 hosts 文件,然后运行下面命令
php artisan serve --host www.lv8.com
-
创建一个API-Controller
php artisan make:controller UserController --api
在UserController 中的 index 写个
return 'index';
. -
然后再
routes/api.php
中引入API-Controllerphpuse App\Http\Controllers\UserController; Route::apiResourcce('users', UserController::class);
-
检查一下路由是否有效
php artisan route:list
现在是可以请求
www.lv8.com:8000/api/users
4.生成标准API
专门创建一个API抽象类,并继承调用它。
生成标准API
-
创建一个抽象类
BaseController
实现一个生成API的方法,让控制器继承;php artisan make:controller BaseController
php/** * Class BaseController * @package App\Http\Controllers * api 基类 */ abstract class BaseController extends Controller { // 生成api方法 protected function create($data, $msg = '', $code = 200) { // 返回api结果 $result = [ // 状态码 'code' => $code, //自定义信息 'msg' => $msg, // 数据返回 'data' => $data ]; return response($result, $code); } }
-
在
UserController
中继承上面的抽象类phpclass UserController extends BaseController { public function index() { return $this->create([1,2,3], '数据获取成功',200); // 当前类是 BaseController 的子类,create是继承后的方法 }
继承后直接使用
$this
来调用抽象类的方法
5.数据列表和分页
数据列表返回
-
创建一个
Model/User
,用于数据库模型处理,用命令生成;php artisan make:model api/User
php// 空模型即可 class User extends Model { use HasFactory; }
-
注意配置数据库连接,账号、密码、数据库名、前缀等
-
使用模型方式调用数据库链接,并返回数据
php// 在 UserController 中 use App\Models\api\User; public function index() { $reslut = User::select('id', 'username', 'email')->get(); // 这里只要了三个字段 return $this->create($reslut, '数据获取成功',200); // 使用 paginate 来进行分页 // return $this->create(User::select('id', 'username', 'email')->paginate(5), '数据获取成功',200); // 这里是前五条数据 // return $this->create(User::select('id', 'username', 'email')->simplePaginate(5), '数据获取成功',200); // 简洁版 }
注意:这里就已经连接数据库了。
分页操作:没有太多需求的话,一般使用简单形式
simplePaginate
.测试接口:
http://www.lv8.com:8000/api/users?page=2
6.配置404错误
首先规范一下错误状态的状态码,具体说明如下:
- 200(OK)-表示已在响应中发出
- 204(无内容) - 资源有空表示,请求成功,但无数据
- 301(Moved Permanently) - 资源的URI已被更新
- 303 (See Other) -其他(如,负载均衡)
- 304 (not modified) -资源未更改(缓存)
- 400 (bad request)- 指代坏请求(如,参数错误)
- 404 (not found)- 资源不存在(找不到页面)
- 406 (not acceptable)- 服务端不支持所需表示
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务端当前无法处理请求
框架已经非常智能的提供了404的处理,只要固定路径配置 404 错误页即可;
覆盖掉系统自带的404:resources/views/errors/404.blade.php
php
<?php
/*
* API格式
* path:resources/views/errors/404.blade.php
* */
// 设置 HTTP 状态码为 404
http_response_code(404);
// 设置响应头为 JSON 格式
header('Content-Type: application/json');
$result = [
// 状态码
'code' => 404,
// 自定义信息
'msg' => '资源不存在~',
// 数据返回, 返回一个空
'data' => []
];
echo json_encode($result); // 必须要加 json_encode 格式转换
7.单数据处理及错误
-
资源控制器中 show,表示获取单一数据,传递id参数即可
-
那么,我们在show 方法里构造获取方式,具体如下:
位置:
UserController.php
phppublic function show($id) { // 判断id 合法 if(!is_numeric($id)){ return $this->create([], 'id参数错误!!!', 400); } // 获取数据 $result = User::select('id', 'username', 'email')->find($id); // 通过id查找 // 判断是否为空 if(empty($result)){ return $this->create([], '请求成功,但无数据~', 204); } else { return $this->create($result, '数据获取成功~', 200); } }
PS:路由地址为:
http://www.lv8.com:8000/api/users/20
注意,需要把 BaseController
中的 return
修改一下
php
class BaseController extends Controller
{
// 生成api方法
protected function create($data, $msg = '', $code = 200)
{
// 返回api结果
$result = [
// 状态码
'code' => $code,
// 自定义信息
'msg' => $msg,
// 数据返回
'data' => $data
];
return response($result);
}
}
8.新增数据API处理
- 新增一条数据,首先要进行验证,这里找事服务器端的,用验证器即可
- 使用Postman来模拟新增时,选择Body中的form-data(表单),并用POST;
添加数据函数
php
public function store(Request $request) // post 进入
{
// 获取提交数据
$data = $request->all();
// 数据验证,required 不可为空, unique 唯一,
$validator = Validator::make($data, [
'username' => 'required|unique:users|min:2|max:10', // 2 < length < 10
'password' => 'required|min:6', // x > 6
]);
// 验证并提示
if ($validator->fails()) { // fails 如果发生错误
// return $this->create([], "提交的数据有误~", 400);
return $this->create([], $validator->errors(), 400); // $validator->errors() 是框架自带的错误提示英文
} else {
// 写入数据
$addData = User::create($data);
// 存在,说明成功了
if ($addData) {
return $this->create($data, '数据添加成功~', 200);
}
}
return $data;
// 数据验证
// $validator
}
数据验证
规则 | 说明 | 示例 |
---|---|---|
required |
字段必填(非空) | 'email' => 'required' |
nullable |
允许字段为 null |
'phone' => 'nullable' |
string |
必须是字符串类型 | 'name' => 'string' |
min:value |
最小长度/值(字符串、数组、数值) | 'password' => 'min:6' |
max:value |
最大长度/值 | 'username' => 'max:20' |
email |
验证邮箱格式 | 'email' => 'email' |
unique:table |
数据库唯一性校验 | 'username' => 'unique:users' |
exists:table |
值必须存在于数据库 | 'role' => 'exists:roles,name' |
confirmed |
与 字段名_confirmation 匹配 |
'password' => 'confirmed' |
in:value1,value2 |
值必须在指定列表内 | 'status' => 'in:active,pending' |
numeric |
必须是数字 | 'age' => 'numeric' |
date |
验证日期格式(如 Y-m-d ) |
'birthday' => 'date' |
php
// 用户名(必填+唯一+长度限制)
'username' => 'required|unique:users|min:2|max:10',
// 密码(必填+最小长度+确认)
'password' => 'required|min:6|confirmed'
// 邮箱(必填+格式验证)
'email' => 'required|email'
⚡ 快捷记忆口诀
-
必填非空 :
required
-
数据类型 :
string
、numeric
、integer
-
长度控制 :
min
/max
/size
-
唯一性 :
unique
(数据库校验) -
格式验证 :
email
、url
、date
-
二次确认 :
confirmed
(如密码确认)
许可赋值 App\Models\api;
php
<?php
namespace App\Models\api;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use HasFactory;
// 许可赋值
protected $fillable = ['username', 'password','email', 'details'];
}
9.删除数据API处理
删除API DELETE
- API删除,使用DELETE动词既可
php
public function destroy($id)
{
// 判断id 合法
if(!is_numeric($id)){
return $this->create([], 'id参数错误!!!', 400);
}
// 查找数据,并删除 find
$users = User::find($id);
// 删除的数据不存在
if(empty($users)){
return $this->create([], '数据不存在~', 400);
}
// 执行删除返回
if($users->delete()){
return $this->create([], '数据删除成功~', 200);
}
return $this->create([], '请求成功,删除失败~', 200);
}
使用DELETE
方式,请求地址:http://www.lv8.com:8000/api/users/20
Controller
.
php
<?php
namespace App\Http\Controllers;
use App\Models\api\client;
use Illuminate\Http\Request;
class ClientController extends BaseController
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
// 获取全部数据
$data = client::select('id', 'email', 'password_hash', 'phone_number', 'first_name', 'last_name')->get();
return $this->create($data, 'success', 200);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// 验证请求数据
$validatedData = $request->validate([
'email' => 'required|email|unique:clients',
'password_hash' => 'required',
'phone_number' => 'required',
'first_name' => 'required',
'last_name' => 'required'
]);
// 创建新的客户端记录
$client = client::create($validatedData);
return $this->create($client, 'Client created successfully', 201);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
// 单数据处理
// 判断id是否合法
if(!is_numeric($id)){
return $this->create([], 'id参数错误~', 400);
}
// 获取数据
$reslut = client::select('id', 'email', 'password_hash', 'phone_number', 'first_name', 'last_name')->find($id);
// 判断是否为空
if(empty($reslut)){
return $this->create([], '请求成功但无数据~', 200);
}
return $this->create($reslut, 'success', 200);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
// 判断id是否合法
if(!is_numeric($id)){
return $this->create([], 'id参数错误~', 400);
}
// 查找要更新的客户端记录
$client = client::find($id);
if (!$client) {
return $this->create([], 'Client not found', 404);
}
// 验证请求数据
$validatedData = $request->validate([
'email' => 'email|unique:clients,email,'.$id,
'password_hash' => 'sometimes',
'phone_number' => 'sometimes',
'first_name' => 'sometimes',
'last_name' => 'sometimes'
]);
// 更新客户端记录
$client->update($validatedData);
return $this->create($client, 'Client updated successfully', 200);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
// 判断id是否合法
if(!is_numeric($id)){
return $this->create([], 'id参数错误~', 400);
}
// 查找要删除的客户端记录
$client = client::find($id);
if (!$client) {
return $this->create([], 'Client not found', 404);
}
// 删除客户端记录
$client->delete();
return $this->create([], 'Client deleted successfully', 200);
}
}
axios
,用例
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
table {
font-size: 18px;
border-collapse: collapse;
width: 700px;
height: 80px;
margin: 0 auto;
text-align: center;
}
th {
width: 100px;
height: 68px;
padding: 8px 12px;
background: yellowgreen;
}
table,th,td {
border: 1px solid yellowgreen;
}
</style>
</head>
<body>
<h1>表格</h1>
<table class="table">
<tr>
<th>id</th>
<th>username</th>
<th>gender</th>
<th>email</th>
<th>price</th>
</tr>
</table>
<script type="text/javascript">
const table = document.querySelector(".table>tbody");
let data_str = table.innerHTML;
axios({
method: 'get',
url: 'https://cdn.liyanhui.com/data.json',
// data: {}
}).then((res) => {
// data = res.data;
res.data.forEach((value) =>{
data_str += `<tr><td>${value.id}</td>
<td>${value.username}</td>
<td>${value.gender}</td>
<td>${value.email}</td>
<td>${value.price}</td></tr>`;
})
table.innerHTML = data_str;
});
</script>
</body>
</html>