首页 > php框架 > Laravel > 正文

如何在Laravel中创建RESTful API

幻夢星雲
发布: 2025-07-12 15:51:01
原创
421人浏览过

直接答案是:在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)

阿里妈妈·创意中心
阿里妈妈·创意中心

阿里妈妈营销创意中心

阿里妈妈·创意中心 0
查看详情 阿里妈妈·创意中心

我个人觉得,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就能构建起一套强大而安全的访问控制体系。

以上就是如何在Laravel中创建RESTful API的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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