第5.2章:创建简单的API视图
学习时间: 45分钟
1. 任务:可视化数据
我们在第2章中的API能够以JSON格式返回数据。这对于机器来说很棒,但人们更喜欢在美观的网页上查看信息。我们的目标是创建两个这样的页面:
- 所有行星列表 (
/planets
) - 单个行星页面 (
/planets/{id}
)
为此,我们将使用“路由 → 控制器 → 视图”组合。
💡 太空类比:
想象一下,API返回的JSON是原始遥测数据,只是一串数字流。我们今天的任务是在任务控制中心创建两个屏幕(两个“视图”):
- 概览屏幕: 显示系统中所有对象的状态(行星列表)。
- 详细屏幕: 点击对象时显示其所有信息(单个行星页面)。
2. 步骤1:创建网页控制器
为了架构的清晰,不应将API逻辑和网页逻辑混合在同一个控制器中。我们将创建一个新的控制器,专门用于显示我们的Blade视图。
在终端中执行:
我们将其创建在Web
子文件夹中,以便与API控制器区分开来。
打开创建的文件 app/Http/Controllers/Web/PlanetPageController.php
。
步骤2:所有行星列表页面
1. 在控制器中创建方法:
在 PlanetPageController
中添加 index
方法,该方法将从数据库中获取所有行星并将其传递给视图。
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Models\Planet; // 别忘了导入模型
class PlanetPageController extends Controller
{
/**
* 显示所有行星列表页面。
*/
public function index()
{
// 1. 从数据库中获取所有行星
$planets = Planet::all();
// 2. 返回视图并传递数据
return view('planets.index', ['planets' => $planets]);
}
}
2. 创建Blade视图:
创建文件 resources/views/planets/index.blade.php
。我们将使用上一章中创建的布局。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>行星</title>
<style>
body {
font-family: sans-serif;
background-color: #f4f4f9;
color: #333;
margin: 0;
padding: 2em;
}
.container {
max-width: 960px;
margin: 0 auto;
}
h2 {
color: #1a202c;
}
hr {
border: none;
border-top: 1px solid #e2e8f0;
margin: 1.5em 0;
}
.planet-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5em;
}
.planet-card {
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.5em;
padding: 1.5em;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: transform 0.2s;
}
.planet-card:hover {
transform: translateY(-5px);
}
.planet-card h3 {
margin-top: 0;
color: #2d3748;
}
.planet-card p {
margin-bottom: 0.5em;
color: #4a5568;
}
.planet-card a {
color: #4299e1;
text-decoration: none;
font-weight: bold;
}
.planet-card a:hover {
text-decoration: underline;
}
.no-planets {
color: #718096;
}
</style>
</head>
<body>
<div class="container">
<h2>所有已知行星列表</h2>
<hr>
<div class="planet-list">
@forelse($planets as $planet)
<div class="planet-card">
<h3>{{ $planet->name }}</h3>
<p>太阳系:{{ $planet->solar_system }}</p>
<p>直径:{{ number_format($planet->size_km, 0, '.', ' ') }} 公里</p>
<a href="/planets/{{ $planet->id }}">了解更多 →</a>
</div>
@empty
<p class="no-planets">数据库中没有行星。请运行数据填充器。</p>
@endforelse
</div>
</div>
</body>
</html>
number_format(...)
是一个普通的PHP函数,用于美观地格式化数字。它可以在Blade中直接使用。
3. 在 routes/web.php
中创建路由:
use App\Http\Controllers\Web\PlanetPageController;
// ...
Route::get('/planets', [PlanetPageController::class, 'index']);
/planets
地址,您将看到行星列表页面!
4. 步骤3:单个行星页面
1. 在控制器中创建方法:
在 PlanetPageController
中添加 show
方法。通过路由模型绑定(Route Model Binding),Laravel将根据ID自动找到行星并将其传递给方法。
<?php
// 在 PlanetPageController 类内部
/**
* 显示单个具体行星的页面。
*/
public function show(Planet $planet)
{
// Laravel 已经为我们找到了行星。
// 如果未找到,它将自动返回 404 错误。
return view('planets.show', ['planet' => $planet]);
}
2. 创建Blade视图:
创建文件 resources/views/planets/show.blade.php
。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ $planet->name }}</title>
<style>
body {
font-family: sans-serif;
background-color: #f4f4f9;
color: #333;
margin: 0;
padding: 2em;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
max-width: 600px;
width: 100%;
}
.planet-detail {
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.5em;
padding: 2em;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.planet-detail h1 {
margin-top: 0;
color: #2d3748;
}
.planet-detail p {
margin-bottom: 1em;
color: #4a5568;
font-size: 1.1em;
}
.back-link {
display: inline-block;
margin-top: 1.5em;
color: #4299e1;
text-decoration: none;
font-weight: bold;
}
.back-link:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<div class="planet-detail">
@if($planet->image_url)
<img src="{{ $planet->image_url }}" alt="{{ $planet->name }}的图片" style="max-width: 100%; height: auto; border-radius: 0.5em; margin-bottom: 1em;">
@endif
<h1>{{ $planet->name }}</h1>
@if($planet->description)
<p>{{ $planet->description }}</p>
@endif
<p><strong>太阳系:</strong> {{ $planet->solar_system }}</p>
<p><strong>直径:</strong> {{ number_format($planet->size_km, 0, '.', ' ') }} 公里</p>
<a href="/planets" class="back-link">← 返回行星列表</a>
</div>
</div>
</body>
</html>
3. 在 routes/web.php
中创建路由:
{planet}
必须与控制器方法中的变量名称 (show(Planet $planet)
) 匹配,以便路由模型绑定正常工作。
现在,点击列表页面上的“了解更多”链接,您将进入特定行星的详细页面。
巩固练习小测验
🚀 本章总结:
您已成功使用 Laravel MVC 架构为您的 API 创建了“前端展示”。现在您拥有:
- 用于网页逻辑的独立控制器。
- 一个动态页面,列出所有行星,并从数据库获取数据。
- 每个行星的详细页面,使用路由模型绑定(Route Model Binding)。
- 在
routes/web.php
中定义了两个 Web 路由,用于访问这些页面。
您已将原始数据转换为用户可理解且有用的信息。 在下一章中,我们将通过将 JavaScript 嵌入到我们的 Blade 视图中来增加交互性,以实现在不重新加载页面的情况下与 API 进行交互。