0

0

如何在Laravel中创建RESTful API

幻夢星雲

幻夢星雲

发布时间:2025-07-12 15:51:01

|

443人浏览过

|

来源于php中文网

原创

直接答案是:在laravel中构建restful api需要通过定义路由、创建控制器、使用api资源进行数据转换,并结合sanctum实现认证与授权。1. 定义api路由时,将所有api相关路由集中放在routes/api.php文件中,并使用route::apiresource()生成标准crud路由,同时为版本管理添加前缀如v1;2. 创建api控制器时,使用php artisan make:controller --api生成仅包含必要方法的控制器,并实现index、store、show、update和destroy等操作;3. 使用api资源类(如通过php artisan make:resource生成)来控制模型序列化格式,统一返回结构并优化关联数据加载;4. 在认证方面,使用laravel sanctum提供轻量级api令牌认证,在用户模型引入hasapitokens trait,并通过createtoken()生成令牌;5. 授权方面,使用策略(policy)封装特定模型的访问控制逻辑,并在控制器中调用$this->authorize()进行权限验证;6. 统一响应格式与状态码,如成功时返回200、201或204,错误时根据情况返回400、401、403、404、422或500等,并在响应体中包含清晰的信息结构。

如何在Laravel中创建RESTful API

如果你问我如何在Laravel里搞一个RESTful API,我的直接答案是:它其实就是一套约定俗成的规矩,加上Laravel本身提供的那些趁手的工具,比如路由、控制器、Eloquent ORM,以及非常实用的API资源和Sanctum认证。核心在于把你的业务逻辑抽象成一个个资源,然后通过HTTP动词去操作它们。说实话,刚开始接触API的时候,我也曾被那些HTTP动词和状态码搞得有点晕,但一旦你理解了RESTful的核心思想——资源导向,一切就豁然开朗了。

解决方案

在Laravel中创建RESTful API,通常我会这样一步步来:

  1. 定义API路由: 所有API相关的路由都放在routes/api.php文件里。Laravel提供了一个非常方便的Route::apiResource方法,它能自动为你的资源生成标准的CRUD(创建、读取、更新、删除)路由。

    // routes/api.php
    use App\Http\Controllers\Api\V1\PostController;
    use Illuminate\Support\Facades\Route;
    
    Route::prefix('v1')->group(function () {
        Route::apiResource('posts', PostController::class);
        // 如果需要,还可以定义一些非标准的动作
        Route::post('posts/{post}/publish', [PostController::class, 'publish']);
    });

    这里我加了个v1前缀,因为API版本管理是个好习惯,未来升级时能少踩很多坑。

  2. 创建API控制器: 使用Artisan命令可以快速生成一个API控制器。--api标志会生成一个不包含createedit方法的控制器,这符合API的无状态特性。

    php artisan make:controller Api/V1/PostController --api

    在控制器里,你需要实现index(获取列表)、store(创建)、show(获取详情)、update(更新)和destroy(删除)等方法。

    // app/Http/Controllers/Api/V1/PostController.php
    namespace App\Http\Controllers\Api\V1;
    
    use App\Http\Controllers\Controller;
    use App\Http\Resources\PostResource; // 稍后会创建
    use App\Models\Post;
    use Illuminate\Http\Request;
    use Illuminate\Validation\ValidationException;
    
    class PostController extends Controller
    {
        public function index()
        {
            $posts = Post::latest()->paginate(10);
            return PostResource::collection($posts); // 使用资源集合返回
        }
    
        public function store(Request $request)
        {
            try {
                $validatedData = $request->validate([
                    'title' => 'required|string|max:255',
                    'content' => 'required|string',
                    // ... 其他验证规则
                ]);
    
                $post = Post::create($validatedData);
                return new PostResource($post); // 返回新创建的资源
            } catch (ValidationException $e) {
                return response()->json([
                    'message' => 'Validation Failed',
                    'errors' => $e->errors()
                ], 422);
            }
        }
    
        public function show(Post $post)
        {
            return new PostResource($post);
        }
    
        public function update(Request $request, Post $post)
        {
            try {
                $validatedData = $request->validate([
                    'title' => 'sometimes|string|max:255',
                    'content' => 'sometimes|string',
                ]);
    
                $post->update($validatedData);
                return new PostResource($post);
            } catch (ValidationException $e) {
                return response()->json([
                    'message' => 'Validation Failed',
                    'errors' => $e->errors()
                ], 422);
            }
        }
    
        public function destroy(Post $post)
        {
            $post->delete();
            return response()->json(null, 204); // 204 No Content,表示成功删除
        }
    
        public function publish(Post $post)
        {
            $post->update(['published_at' => now()]);
            return new PostResource($post);
        }
    }
  3. 创建API资源: 这是我个人在使用Laravel构建API时,最喜欢的一点。API资源允许你轻松地将模型转换为JSON格式,并且可以控制哪些属性应该被包含,甚至可以添加自定义属性。

    php artisan make:resource PostResource
    // app/Http/Resources/PostResource.php
    namespace App\Http\Resources;
    
    use Illuminate\Http\Resources\Json\JsonResource;
    
    class PostResource extends JsonResource
    {
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'title' => $this->title,
                'content' => $this->content,
                'slug' => $this->slug,
                'created_at' => $this->created_at->format('Y-m-d H:i:s'),
                'updated_at' => $this->updated_at->format('Y-m-d H:i:s'),
                // 你可以根据需要添加关联数据,比如作者信息
                // 'author' => new UserResource($this->whenLoaded('user')),
            ];
        }
    }
  4. 认证与授权: 对于API,Laravel Sanctum是一个非常棒的选择,尤其适合单页面应用(SPA)和移动应用。它提供了一种轻量级的API令牌认证系统。

    composer require laravel/sanctum
    php artisan vendor:publish --tag=sanctum-config
    php artisan migrate

    然后在你的User模型中引入HasApiTokens trait。

    // app/Models/User.php
    use Laravel\Sanctum\HasApiTokens;
    
    class User extends Authenticatable
    {
        use HasApiTokens, Notifiable;
        // ...
    }

    这样,用户登录后就可以生成API令牌,客户端使用这个令牌进行后续请求。

如何设计一个清晰、可维护的Laravel API路由结构?

设计API路由结构,在我看来,最重要的是“一致性”和“可预测性”。当你的API变得庞大时,一个混乱的路由会让开发者抓狂。

首先,版本化是必须的。我通常会把API版本放在URL路径中,比如/api/v1/posts。这样当你的API需要进行重大更新时,可以发布/api/v2/posts,而不会影响到使用旧版本API的客户端。Laravel的Route::prefix('v1')或者Route::group(['prefix' => 'v1'])可以很好地实现这一点。

其次,资源化命名是RESTful的核心。URL应该代表资源,而不是操作。例如,获取所有文章是/posts,获取单篇文章是/posts/{id}。操作通过HTTP动词(GET, POST, PUT/PATCH, DELETE)来区分。Laravel的Route::apiResource('posts', PostController::class)就是这一思想的完美体现,它会自动帮你生成一套标准的资源路由。如果你有嵌套资源,比如获取某篇文章的所有评论,可以考虑/posts/{post}/comments

再者,命名空间和分组能让你的路由文件更整洁。把API控制器放在App\Http\Controllers\Api\V1这样的命名空间下,并在路由文件中使用Route::namespace('Api\V1')->group(...)或者直接在apiResource里指定完整的控制器路径,能有效避免命名冲突,也让文件结构一目了然。

最后,对于那些不完全符合RESTful规范的“自定义”操作,比如文章发布,我倾向于将其作为资源的子路由,或者使用一个明确的动词,例如POST /posts/{post}/publish。这比使用GET /posts/publish/{post_id}要好得多,因为它更明确地表示这是一个对特定文章的“动作”。

在Laravel API中如何处理数据转换和响应格式?

数据转换和响应格式是API的“面子工程”,直接影响到客户端的开发体验。Laravel在这方面提供了非常强大的工具,那就是API资源(API Resources)

Zend_API 深入_PHP_内核
Zend_API 深入_PHP_内核

”扩展PHP“说起来容易做起来难。PHP已经进化成一个日趋成熟的源码包几十兆大小的工具。要骇客如此复杂的一个系统,不得不学习和思考。构建本章内容时,我们最终选择了“在实战中学习”的方式。这不是最科学也不是最专业的方式,但是此方式最有趣,也得出了最好的最终结果。下面的部分,你将先快速的学习到,如何获得最基本的扩展,且这些扩展立即就可运行。然后你将学习到 Zend 的高级 API 功能,这种方式将不得

下载

我个人觉得,API资源是Laravel在API开发方面最亮眼的功能之一。它解决了两个核心问题:

  1. 数据过滤:你可能不想把数据库里所有的字段都暴露给客户端,比如用户的密码哈希值。API资源让你精确控制哪些字段应该被序列化。
  2. 数据整形:有时候,数据库字段名可能不符合API的命名规范(比如snake_case vs camelCase),或者你需要对数据进行一些计算或格式化(比如日期格式)。资源允许你自定义这些。

使用php artisan make:resource YourResource创建一个资源类后,你可以在toArray方法里定义返回的数据结构。对于单个模型,使用new YourResource($model);对于模型集合或分页结果,使用YourResource::collection($collection)

// 假设有一个 UserResource
public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'profile_url' => url('/users/' . $this->id), // 可以添加计算属性
        'posts_count' => $this->whenLoaded('posts', fn() => $this->posts->count()), // 条件加载关联数据
    ];
}

whenLoaded方法特别有用,它只会在关联关系已经被加载时才包含该数据,避免了N+1查询问题。

统一的响应格式也至关重要。我通常会约定一个标准的JSON响应结构,尤其是在处理错误时。例如,成功响应可能直接返回数据,而错误响应则包含messageerrors(如果涉及验证失败)和code(HTTP状态码)等字段。

// 成功响应
{
    "data": {
        "id": 1,
        "title": "我的第一篇文章"
        // ...
    }
}

// 验证失败响应
{
    "message": "The given data was invalid.",
    "errors": {
        "title": [
            "标题不能为空。"
        ],
        "content": [
            "内容必须至少包含10个字符。"
        ]
    }
}

// 其他错误响应
{
    "message": "资源未找到。",
    "code": 404
}

在控制器中,你可以使用response()->json(...)来构建这些响应。HTTP状态码的正确使用也同样重要,比如200 OK、201 Created、204 No Content、400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found、422 Unprocessable Entity、500 Internal Server Error等。

Laravel API的认证与授权有哪些推荐实践?

API的认证和授权,在我看来,是确保数据安全的关键环节。Laravel提供了几种方式,但对于API,我最推荐的是Laravel Sanctum

认证 (Authentication): Sanctum是一个轻量级的API认证系统,它支持两种主要的使用场景:

  1. SPA认证:对于单页面应用,Sanctum通过基于Cookie的会话认证来提供无缝的用户体验。它会为你处理CSRF保护和会话管理,让前端可以像传统Web应用一样直接调用API。
  2. API令牌认证:这是最常见的API认证方式,适用于移动应用、第三方服务或者需要无状态认证的场景。用户登录后,你可以为他们生成一个API令牌(Personal Access Token),客户端将这个令牌放在HTTP请求的Authorization头(Bearer Token)中发送给服务器。

在用户模型上使用HasApiTokens trait后,你可以通过$user->createToken('token-name')来生成令牌,并通过$request->user('sanctum')来获取当前认证的用户。

// 登录并生成令牌示例
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

public function login(Request $request)
{
    if (!Auth::attempt($request->only('email', 'password'))) {
        return response()->json(['message' => 'Invalid credentials'], 401);
    }

    $user = Auth::user();
    $token = $user->createToken('auth_token')->plainTextToken; // 生成令牌

    return response()->json([
        'message' => 'Login successful',
        'access_token' => $token,
        'token_type' => 'Bearer',
    ]);
}

// 保护API路由
Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', function (Request $request) {
        return $request->user();
    });
});

授权 (Authorization): 认证是“你是谁”,授权是“你能做什么”。Laravel的授权机制包括Gates(门禁)Policies(策略)。对于复杂的资源操作,我更倾向于使用策略,因为它能将特定模型的授权逻辑封装在一个类中,让代码更清晰、更易于维护。

例如,你可以为Post模型创建一个策略:

php artisan make:policy PostPolicy --model=Post
// app/Policies/PostPolicy.php
namespace App\Policies;

use App\Models\User;
use App\Models\Post;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
    use HandlesAuthorization;

    public function view(User $user, Post $post)
    {
        return true; // 任何人都可以查看文章
    }

    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id; // 只有文章作者才能更新
    }

    public function delete(User $user, Post $post)
    {
        return $user->id === $post->user_id; // 只有文章作者才能删除
    }
}

然后在AuthServiceProvider中注册策略:

// app/Providers/AuthServiceProvider.php
protected $policies = [
    Post::class => PostPolicy::class,
];

最后,在控制器中使用$this->authorize()方法进行授权检查:

// app/Http/Controllers/Api/V1/PostController.php
public function update(Request $request, Post $post)
{
    $this->authorize('update', $post); // 检查当前用户是否有权更新此文章
    // ... 更新逻辑
}

public function destroy(Post $post)
{
    $this->authorize('delete', $post); // 检查当前用户是否有权删除此文章
    // ... 删除逻辑
}

如果授权失败,Laravel会自动抛出一个AuthorizationException,并返回403 Forbidden响应,这非常符合API的规范。通过结合Sanctum进行认证,再配合策略进行授权,你的Laravel API就能构建起一套强大而安全的访问控制体系。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2652

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1658

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1515

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

952

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1418

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1234

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1468

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1306

2023.11.13

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

72

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Laravel---API接口
Laravel---API接口

共7课时 | 0.6万人学习

PHP自制框架
PHP自制框架

共8课时 | 0.6万人学习

PHP面向对象基础课程(更新中)
PHP面向对象基础课程(更新中)

共12课时 | 0.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号