php消息路由
1.单文件模式
web刚开始发展的时候,没有专门的前端工程师, web开发人员经常是服务端,客户端开发一把梭。那时候,不管是业务逻辑,还是界面交互,都喜欢把某个业务的前后端代码放在同一个文件。例如,jsp,asp,php均是这种模式。
例如,下面的订单管理页面,主要负责订单的增删查改
<?php
// 连接数据库
try {
$pdo = new PDO('mysql:host=localhost;dbname=php', 'root', '123456');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("数据库连接失败:" . $e->getMessage());
}
// 获取所有订单
function getAllOrders()
{
global $pdo;
$sql = "SELECT * FROM orders";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 添加订单
function addOrder($customerName, $productName, $quantity, $totalPrice)
{
global $pdo;
$sql = "INSERT INTO orders (customer_name, product_name, quantity, total_price) VALUES (:customer_name, :product_name, :quantity, :total_price)";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':customer_name', $customerName);
$stmt->bindParam(':product_name', $productName);
$stmt->bindParam(':quantity', $quantity);
$stmt->bindParam(':total_price', $totalPrice);
$stmt->execute();
}
// 更新订单
function updateOrder($id, $customerName, $productName, $quantity, $totalPrice)
{
global $pdo;
$sql = "UPDATE orders SET customer_name = :customer_name, product_name = :product_name, quantity = :quantity, total_price = :total_price WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->bindParam(':customer_name', $customerName);
$stmt->bindParam(':product_name', $productName);
$stmt->bindParam(':quantity', $quantity);
$stmt->bindParam(':total_price', $totalPrice);
$stmt->execute();
}
// 删除订单
function deleteOrder($id)
{
global $pdo;
$sql = "DELETE FROM orders WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();
}
// 根据请求类型进行处理
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['action']) && $_POST['action'] === 'add') {
addOrder($_POST['customer_name'], $_POST['product_name'], $_POST['quantity'], $_POST['total_price']);
} elseif (isset($_POST['action']) && $_POST['action'] === 'update') {
updateOrder($_POST['id'], $_POST['customer_name'], $_POST['product_name'], $_POST['quantity'], $_POST['total_price']);
} elseif (isset($_POST['action']) && $_POST['action'] === 'delete') {
deleteOrder($_POST['id']);
}
header('Location: index.php');
exit;
}
$orders = getAllOrders();
?>
<!DOCTYPE html>
<html>
<head>
<title>订单管理系统</title>
<style>
body {
font-family: Arial, sans-serif;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
padding: 8px;
border: 1px solid #ddd;
}
th {
background-color: #f2f2f2;
}
.btn {
padding: 6px 12px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-primary {
background-color: #007bff;
color: #fff;
}
.btn-danger {
background-color: #dc3545;
color: #fff;
}
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.4);
}
.modal-content {
background-color: #fff;
margin: 10% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
.modal-header,
.modal-footer {
padding: 10px;
}
.modal-title {
margin: 0;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
input[type="number"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="container">
<h1>订单管理系统</h1>
<table>
<thead>
<tr>
<th>订单编号</th>
<th>客户名称</th>
<th>产品名称</th>
<th>数量</th>
<th>总价</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<tr>
<td><?php echo $order['id']; ?></td>
<td><?php echo $order['customer_name']; ?></td>
<td><?php echo $order['product_name']; ?></td>
<td><?php echo $order['quantity']; ?></td>
<td><?php echo $order['total_price']; ?></td>
<td>
<button class="btn btn-primary btn-sm edit-btn" data-id="<?php echo $order['id']; ?>" data-customer_name="<?php echo $order['customer_name']; ?>" data-product_name="<?php echo $order['product_name']; ?>" data-quantity="<?php echo $order['quantity']; ?>" data-total_price="<?php echo $order['total_price']; ?>">编辑</button>
<button class="btn btn-danger btn-sm delete-btn" data-id="<?php echo $order['id']; ?>">删除</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<button class="btn btn-success" onclick="showAddModal()">添加订单</button>
</div>
<!-- 添加订单模态框 -->
<div id="addModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h5 id="addModalLabel">添加订单</h5>
<button type="button" class="close" onclick="hideModal('addModal')">×</button>
</div>
<div class="modal-body">
<form id="addForm">
<div class="form-group">
<label for="customer_name">客户名称</label>
<input type="text" class="form-control" id="customer_name" required>
</div>
<div class="form-group">
<label for="product_name">产品名称</label>
<input type="text" class="form-control" id="product_name" required>
</div>
<div class="form-group">
<label for="quantity">数量</label>
<input type="number" class="form-control" id="quantity" required>
</div>
<div class="form-group">
<label for="total_price">总价</label>
<input type="number" class="form-control" id="total_price" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="hideModal('addModal')">关闭</button>
<button type="button" class="btn btn-primary" onclick="addOrder()">添加</button>
</div>
</div>
</div>
<!-- 编辑订单模态框 -->
<div id="editModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h5 id="editModalLabel">编辑订单</h5>
<button type="button" class="close" onclick="hideModal('editModal')">×</button>
</div>
<div class="modal-body">
<form id="editForm">
<input type="hidden" id="edit_id">
<div class="form-group">
<label for="edit_customer_name">客户名称</label>
<input type="text" class="form-control" id="edit_customer_name" required>
</div>
<div class="form-group">
<label for="edit_product_name">产品名称</label>
<input type="text" class="form-control" id="edit_product_name" required>
</div>
<div class="form-group">
<label for="edit_quantity">数量</label>
<input type="number" class="form-control" id="edit_quantity" required>
</div>
<div class="form-group">
<label for="edit_total_price">总价</label>
<input type="number" class="form-control" id="edit_total_price" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="hideModal('editModal')">关闭</button>
<button type="button" class="btn btn-primary" onclick="updateOrder()">保存</button>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
function showAddModal() {
document.getElementById('addModal').style.display = 'block';
}
function hideModal(modalId) {
document.getElementById(modalId).style.display = 'none';
}
// 添加订单
function addOrder() {
const customerName = document.getElementById('customer_name').value;
const productName = document.getElementById('product_name').value;
const quantity = document.getElementById('quantity').value;
const totalPrice = document.getElementById('total_price').value;
$.ajax({
type: 'POST',
url: 'index.php',
data: {
action: 'add',
customer_name: customerName,
product_name: productName,
quantity: quantity,
total_price: totalPrice
},
success: function() {
hideModal('addModal');
location.reload();
}
});
}
// 编辑按钮点击事件
document.addEventListener('click', function(event) {
if (event.target.classList.contains('edit-btn')) {
const id = event.target.dataset.id;
const customerName = event.target.dataset.customer_name;
const productName = event.target.dataset.product_name;
const quantity = event.target.dataset.quantity;
const totalPrice = event.target.dataset.total_price;
document.getElementById('edit_id').value = id;
document.getElementById('edit_customer_name').value = customerName;
document.getElementById('edit_product_name').value = productName;
document.getElementById('edit_quantity').value = quantity;
document.getElementById('edit_total_price').value = totalPrice;
document.getElementById('editModal').style.display = 'block';
}
});
// 保存编辑
function updateOrder() {
const id = document.getElementById('edit_id').value;
const customerName = document.getElementById('edit_customer_name').value;
const productName = document.getElementById('edit_product_name').value;
const quantity = document.getElementById('edit_quantity').value;
const totalPrice = document.getElementById('edit_total_price').value;
$.ajax({
type: 'POST',
url: 'index.php',
data: {
action: 'update',
id: id,
customer_name: customerName,
product_name: productName,
quantity: quantity,
total_price: totalPrice
},
success: function() {
hideModal('editModal');
location.reload();
}
});
}
// 删除按钮点击事件
document.addEventListener('click', function(event) {
if (event.target.classList.contains('delete-btn')) {
const id = event.target.dataset.id;
if (confirm('确定要删除该订单吗?')) {
$.ajax({
type: 'POST',
url: 'index.php',
data: {
action: 'delete',
id: id
},
success: function() {
location.reload();
}
});
}
}
});
</script>
</body>
</html>
这种模式,虽然界面写起来可能不是很漂亮(毕竟术业有专攻),但开发效率还是非常高的。因为服务端客户端都是同一个开发,接口联调如丝般柔顺,减少了沟通的成本。
2.前后端分离模式
伴随javascript的强势发展,现在的web工程基本采用前后端分离的模式,服务端只负责数据的处理,由客户端专门做交互界面。
将下面的代码分成两个文件
2.1.前端界面
<!DOCTYPE html>
<html>
<head>
<title>订单管理系统</title>
<meta charset="UTF-8" />
<style>
body {
font-family: Arial, sans-serif;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
padding: 8px;
border: 1px solid #ddd;
}
th {
background-color: #f2f2f2;
}
.btn {
padding: 6px 12px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-primary {
background-color: #007bff;
color: #fff;
}
.btn-danger {
background-color: #dc3545;
color: #fff;
}
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.4);
}
.modal-content {
background-color: #fff;
margin: 10% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
.modal-header,
.modal-footer {
padding: 10px;
}
.modal-title {
margin: 0;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
input[type="number"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="container">
<h1>订单管理系统</h1>
<table>
<thead>
<tr>
<th>订单编号</th>
<th>客户名称</th>
<th>产品名称</th>
<th>数量</th>
<th>总价</th>
<th>操作</th>
</tr>
</thead>
<tbody id="orderTableBody"></tbody>
</table>
<button class="btn btn-success" onclick="showAddModal()">添加订单</button>
</div>
<!-- 添加订单模态框 -->
<div id="addModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h5 id="addModalLabel">添加订单</h5>
<button type="button" class="close" onclick="hideModal('addModal')">
×
</button>
</div>
<div class="modal-body">
<form id="addForm">
<div class="form-group">
<label for="customer_name">客户名称</label>
<input
type="text"
class="form-control"
id="customer_name"
required
/>
</div>
<div class="form-group">
<label for="product_name">产品名称</label>
<input
type="text"
class="form-control"
id="product_name"
required
/>
</div>
<div class="form-group">
<label for="quantity">数量</label>
<input
type="number"
class="form-control"
id="quantity"
required
/>
</div>
<div class="form-group">
<label for="total_price">总价</label>
<input
type="number"
class="form-control"
id="total_price"
required
/>
</div>
</form>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
onclick="hideModal('addModal')"
>
关闭
</button>
<button type="button" class="btn btn-primary" onclick="addOrder()">
添加
</button>
</div>
</div>
</div>
<!-- 编辑订单模态框 -->
<div id="editModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h5 id="editModalLabel">编辑订单</h5>
<button type="button" class="close" onclick="hideModal('editModal')">
×
</button>
</div>
<div class="modal-body">
<form id="editForm">
<input type="hidden" id="edit_id" />
<div class="form-group">
<label for="edit_customer_name">客户名称</label>
<input
type="text"
class="form-control"
id="edit_customer_name"
required
/>
</div>
<div class="form-group">
<label for="edit_product_name">产品名称</label>
<input
type="text"
class="form-control"
id="edit_product_name"
required
/>
</div>
<div class="form-group">
<label for="edit_quantity">数量</label>
<input
type="number"
class="form-control"
id="edit_quantity"
required
/>
</div>
<div class="form-group">
<label for="edit_total_price">总价</label>
<input
type="number"
class="form-control"
id="edit_total_price"
required
/>
</div>
</form>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
onclick="hideModal('editModal')"
>
关闭
</button>
<button type="button" class="btn btn-primary" onclick="updateOrder()">
保存
</button>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
// 加载订单数据
function loadOrders() {
$.ajax({
type: "GET",
url: "http://localhost/demo/order_handler.php",
success: function (data) {
$("#orderTableBody").html("");
JSON.parse(data).forEach(function (order) {
$("#orderTableBody").append(
"<tr><td>" +
order.id +
"</td><td>" +
order.customer_name +
"</td><td>" +
order.product_name +
"</td><td>" +
order.quantity +
"</td><td>" +
order.total_price +
'</td><td><button class="btn btn-primary btn-sm edit-btn" data-id="' +
order.id +
'" data-customer_name="' +
order.customer_name +
'" data-product_name="' +
order.product_name +
'" data-quantity="' +
order.quantity +
'" data-total_price="' +
order.total_price +
'">编辑</button><button class="btn btn-danger btn-sm delete-btn" data-id="' +
order.id +
'">删除</button></td></tr>'
);
});
},
});
}
loadOrders();
function showAddModal() {
document.getElementById("addModal").style.display = "block";
}
function hideModal(modalId) {
document.getElementById(modalId).style.display = "none";
}
// 添加订单
function addOrder() {
const customerName = document.getElementById("customer_name").value;
const productName = document.getElementById("product_name").value;
const quantity = document.getElementById("quantity").value;
const totalPrice = document.getElementById("total_price").value;
$.ajax({
type: "POST",
url: "http://localhost/demo/order_handler.php",
data: {
action: "add",
customer_name: customerName,
product_name: productName,
quantity: quantity,
total_price: totalPrice,
},
success: function () {
hideModal("addModal");
loadOrders();
},
});
}
// 编辑按钮点击事件
document.addEventListener("click", function (event) {
if (event.target.classList.contains("edit-btn")) {
const id = event.target.dataset.id;
const customerName = event.target.dataset.customer_name;
const productName = event.target.dataset.product_name;
const quantity = event.target.dataset.quantity;
const totalPrice = event.target.dataset.total_price;
document.getElementById("edit_id").value = id;
document.getElementById("edit_customer_name").value = customerName;
document.getElementById("edit_product_name").value = productName;
document.getElementById("edit_quantity").value = quantity;
document.getElementById("edit_total_price").value = totalPrice;
document.getElementById("editModal").style.display = "block";
}
});
// 保存编辑
function updateOrder() {
const id = document.getElementById("edit_id").value;
const customerName =
document.getElementById("edit_customer_name").value;
const product_name = document.getElementById("edit_product_name").value;
const quantity = document.getElementById("edit_quantity").value;
const totalPrice = document.getElementById("edit_total_price").value;
$.ajax({
type: "POST",
url: "/orders/update",
data: {
action: "update",
id: id,
customer_name: customerName,
product_name: product_name,
quantity: quantity,
total_price: totalPrice,
},
success: function () {
hideModal("editModal");
loadOrders();
},
});
}
// 删除按钮点击事件
document.addEventListener("click", function (event) {
if (event.target.classList.contains("delete-btn")) {
const id = event.target.dataset.id;
if (confirm("确定要删除该订单吗?")) {
$.ajax({
type: "POST",
url: "http://localhost/demo/order_handler.php",
data: {
action: "delete",
id: id,
},
success: function () {
loadOrders();
},
});
}
}
});
</script>
</body>
</html>
可以看到,CRUD的路径都是http://localhost/demo/order_handler.php这个php文件,通过action定义子类型。
2.2.后端代码
<?php
require_once 'router.php';
// 连接数据库
try {
$pdo = new PDO('mysql:host=localhost;dbname=php', 'root', '123456');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("数据库连接失败:" . $e->getMessage());
}
// 获取所有订单
function getAllOrders()
{
global $pdo;
$sql = "SELECT * FROM orders";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 添加订单
function addOrder($customerName, $productName, $quantity, $totalPrice)
{
global $pdo;
$sql = "INSERT INTO orders (customer_name, product_name, quantity, total_price) VALUES (:customer_name, :product_name, :quantity, :total_price)";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':customer_name', $customerName);
$stmt->bindParam(':product_name', $productName);
$stmt->bindParam(':quantity', $quantity);
$stmt->bindParam(':total_price', $totalPrice);
$stmt->execute();
}
// 更新订单
function updateOrder($id, $customerName, $productName, $quantity, $totalPrice)
{
global $pdo;
$sql = "UPDATE orders SET customer_name = :customer_name, product_name = :product_name, quantity = :quantity, total_price = :total_price WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->bindParam(':customer_name', $customerName);
$stmt->bindParam(':product_name', $productName);
$stmt->bindParam(':quantity', $quantity);
$stmt->bindParam(':total_price', $totalPrice);
$stmt->execute();
}
// 删除订单
function deleteOrder($id)
{
global $pdo;
$sql = "DELETE FROM orders WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();
}
// 根据请求类型进行处理
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$orders = getAllOrders();
echo json_encode($orders);
} else if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['action']) && $_POST['action'] === 'add') {
addOrder($_POST['customer_name'], $_POST['product_name'], $_POST['quantity'], $_POST['total_price']);
} elseif (isset($_POST['action']) && $_POST['action'] === 'update') {
updateOrder($_POST['id'], $_POST['customer_name'], $_POST['product_name'], $_POST['quantity'], $_POST['total_price']);
} elseif (isset($_POST['action']) && $_POST['action'] === 'delete') {
deleteOrder($_POST['id']);
}
header('Location: index.php');
exit;
}
这里有一段代码,根据不同的请求方法调用相应的函数,就是非常简单(丑陋)的消息路由逻辑了。
// 根据请求类型进行处理
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$orders = getAllOrders();
echo json_encode($orders);
} else if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['action']) && $_POST['action'] === 'add') {
addOrder($_POST['customer_name'], $_POST['product_name'], $_POST['quantity'], $_POST['total_price']);
} elseif (isset($_POST['action']) && $_POST['action'] === 'update') {
updateOrder($_POST['id'], $_POST['customer_name'], $_POST['product_name'], $_POST['quantity'], $_POST['total_price']);
} elseif (isset($_POST['action']) && $_POST['action'] === 'delete') {
deleteOrder($_POST['id']);
}
header('Location: index.php');
exit;
}
3.实现简单路由
3.1.springmvc基于注解的路由
了解过springmvc(或者其他编程语言的mvc框架)的同学,可能对这种代码嗤之以鼻,确实太丑了。springmvc通过类注解,方法注解,定义消息路由,非常漂亮!
@RestController
@RequestMapping("/player")
public class PlayerController {
@GetMapping(value = "/getProgress")
public Response getProgress(@RequestHeader Map<String, String> headers, @Valid ReqQueryProgress req) {
return Response.success(userGameData.getProgress());
}
@PostMapping(value = "/saveProgress")
public Response saveProgress(@RequestHeader Map<String, String> headers, @Valid @RequestBody ReqSaveProgress req) {
return Response.success(userGameData.getProgress());
}
}
由于php不支持注解,无法做到springmvc的模式,即使使用了消息路由,也只能手动注册url与对应的执行函数。
3.2.路由函数(router.php)
<?php
// 定义路由和相关函数等内容
$routes = [];
function route($method, $path, $callback)
{
global $routes;
$routes[$method][$path] = $callback;
}
function dispatch()
{
global $routes;
$method = $_SERVER['REQUEST_METHOD'];
$path = $_SERVER['REQUEST_URI'];
// 本项目放在htdocs目录下的子目录demo,所以将url前缀进行替换
$path = str_replace("/demo", "", $path);
if (isset($routes[$method][$path])) {
$callback = $routes[$method][$path];
return $callback();
} else {
// 404处理
header('HTTP/1.0 404 Not Found');
echo '404 - Page not found';
}
}
3.3.注册业务路由
order_handler.php那段丑陋的代码,现在可以删掉了,改为下面的代码
// 获取订单的路由
route('GET', '/orders', function () {
$orders = getAllOrders();
echo json_encode($orders);
});
// 添加订单的路由
route('POST', '/orders/add', function () {
if (isset($_POST['action']) && $_POST['action'] === 'add') {
addOrder($_POST['customer_name'], $_POST['product_name'], $_POST['quantity'], $_POST['total_price']);
}
header('Location: index.php');
exit;
});
// 更新订单的路由
route('POST', '/orders/update', function () {
if (isset($_POST['action']) && $_POST['action'] === 'update') {
updateOrder($_POST['id'], $_POST['customer_name'], $_POST['product_name'], $_POST['quantity'], $_POST['total_price']);
}
header('Location: index.php');
exit;
});
// 删除订单的路由
route('POST', '/orders/delete', function () {
if (isset($_POST['action']) && $_POST['action'] === 'delete') {
deleteOrder($_POST['id']);
}
header('Location: index.php');
exit;
});
3.4.统一请求入口(网关)
我们希望对order的所有请求转发到order_handler.php这个文件来,这里可以利用.htaccess来定义路由规则,在php代码的同级目录下,新建.htaccess文件,编辑下面的内容。将所有请求转发到index.php。
RewriteEngine On
RewriteRule ^(.*)$ index.php [QSA,L]
在index.php文件,加载路由文件,订单业务处理文件,
<?php
// 引入包含路由定义和相关函数(如addOrder、updateOrder等)的文件
require_once 'router.php';
require_once 'order_handler.php';
// 调用dispatch函数处理请求
dispatch();
// 跨域设置
// 允许任何来源访问
header('Access-Control-Allow-Origin: *');
// 允许的请求方法
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
// 允许的请求头
header('Access-Control-Allow-Headers: Content-Type');
修改客户端请求的url,由统一路径改为具体的路径,如http://localhost/demo/orders/add, action字段也可以去掉了。
3.5.另外一种路由:一个url对应一个文件
对于业务是对各种数据库表作增删查改,则可以换一种方式作映射。对于一张表,增删查改代表四种动作,对应不同的http方法,每一个动作对应一个php文件,采用下面的映射文件。
{
"/api/order/": {
"get": "api/order/query.php",
"post": "api/order/create.php",
"put": "api/order/edit.php",
"delete": "api/order/delete.php",
},
"/api/user/": {
"get": "api/user/query.php",
"post": "api/user/create.php",
"put": "api/user/edit.php",
"delete": "api/user/delete.php",
},
}
通过解析这个文件,得到url与对应的php文件。每次请求,提取出url与method类型,找到对应的php文件,加载后得到计算结果。代码如下:
// 启动一个输出缓冲区
ob_start();
// 根据url,method获取对应的php文件路径
$apiPath = mapAPI($path, $method);
// 加载php文件
include $apiPath;
// 获取缓冲区的结果
$body = ob_get_clean();
// 返回给客户端
return [
'statusCode' => 200,
'headers' => $headers,
'body' => $body
];
这种模式有两个很不好的地方:
- 如果接口很多,文件数据也相应非常多
- 同一张表的增删查改逻辑可能很关联性,拆分成多个文件不利于代码的复用