Laravel文档阅读笔记-How to Build a Rest API with Laravel: A Beginners Guide①

2023-05-16

 

随着移动端和JavaScript框架的发展,比如React和Vue,Restful风格的API越来越流行。使用Restful风格的好处就是一个后端程序可以与多个版本的前端用户界面关联。

Laravel提供了创建Rest API的环境和生态。

首先得导入依赖包比如Laravel Passport和Laravel Sanctum,这两个包提供了Restful API的权限功能,并且使用起来非常简单。

Laravel Breeze包提供了重置密码的模版功能。

Socialite和Scout提供了登陆和查找功能。

Laravel生态圈提供了程序员开发程序时遇到问题的所有解决方案,为开发人员提供最大的开发效率。

此篇教材展示了如何创建Laravel Rest API,并且使用Sanctum进行权限认证。

Resful API是什么?

Resful其实是一种传输状态,是应用间的一种交流方式,这种方式使用了HTTP协议。这种方式是无状态的,短连接的方式,并且不存储seswsion。每个请求都需要像新请求的情况进行处理。

Restful API的好处就是他方便缓存。返回的数据从Redis或Memcached中获取是非常方便的。

一个API是否是Restful分割的,需要满足如下2点:

  • 能够使用URL或Endpoint进行访问;
  • 能够使用Restful方法;
  • 使用HTTP头;
  • 必须返回有效的相应diam

通常Restful方法有如下几种:

GET:获取数据;

POST:新增数据;

PUT/PATCH:更新数据;

DELETE:删除数据;

如何使用Laravel创建REST API

首先创建一个Laravel应用。

laravel new rest 

然后创建model和migration,在这个实例中,使用Products来代表资源。

php artisan make:model Products -m 

-m标签会让Laravel去创建Products模型对应的数据库迁移文件。

下面是模型文件:

//App/Models/Products
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Products extends Model
{

    use HasFactory;

}

下面是模型文件对应的数据库迁移文件:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
};

这里需要手动更新下迁移文件,在文件中添加字段也就是列,这也数据库中也会有对应的字段和列。在Products这个表中添加name、price、description。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->double('price');
            $table->longText('description');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
};

随后在Products模型中将name、price、description注册下。好处是使得数据库字段名和类名一一对应,这样能有效的防止SQL注入,比较安全。

//App/Models/Products
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Products extends Model
{
    use HasFactory;

    protected $fillable = [
        'name', 'price', 'description'
    ];
}

随后在.env文件中添加数据库认证信息:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-rest
DB_USERNAME=root
DB_PASSWORD=password

最后一步是将Products表迁移到数据库里面:

php artisan migrate 

创建数据库Seeder和Factory

在开发的时候需要一些虚拟数据,这也程序员开发起来就比较方便快捷。Laravel提供了Factory facade,并且使用Faker生成仿真数据。

使用下面的命令创建Factory。

php artisan make:factory ProductsFactory

这个文件会在databases/factories文件夹被创建。

这里需要更新下这个文件,改成如下:

//database/factories/ProductsFactory
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Products>
 */
class ProductsFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            'name' => $this->faker->word,
            'price' => $this->faker->numberBetween(1, 99),
            'description' => $this->faker->sentence()
        ];
    }
}

现在factory已经准备好了,下面就是在DatabaseSeeder文件中进行seed。

//database/seeders/DatabaseSeeder
<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        \App\Models\Products::factory(10)->create();
    }
}

使用下面的命令进行seed。

php artisan db:seed

创建控制器

下面创建Products的控制器,这个控制器里面需要编写对于的逻辑,使用下面的命令进行创建。

php artisan make:controller ProductsController -r

-r参数代表resourceful,他会创建http相关的通用请求。

请求包括index、show、store、update、destory,对于这些方法,可以删除、创建、编辑他们,他们并不是都需要,也并不是非要这样命名。下面将Products控制器写成如下。

//App/Http/Controllers/ProductsController

<?php

namespace App\Http\Controllers;

use App\Http\Resources\ProductResource;
use App\Models\Products;
use Illuminate\Http\Request;

class ProductsController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }


    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  Products $product
     * @return \Illuminate\Http\Response
     */
    public function show(Products $product)
    {
        //
    }


    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  Products $product
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Products $product)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  Products $product
     * @return \Illuminate\Http\Response
     */
    public function destroy(Products $product)
    {
        //
    }
}

上面的方法和HTTP中的get、post、patch/put、delete对应。

Index(获取所有产品)

此方法中返回数据库中的所有products:

use App\Models\Products;
public function index()
{
   return Products::all();
}

Show(获取一个产品)

此方法从数据库中获取一个产品,并返回给前端。

通过产品id这个参数获取指定的产品

注意:下面使用的ProductResource()函数,是获取指定产品的,在文章后面将会给出这个函数的详细代码:

use App\Http\Resources\ProductResource;
use App\Models\Products;

public function show(Products $product)
{
   return new ProductResource($product);
}

Store(新增一条产品记录)

使用此方法在数据库中新增一记录,这里使用的是HTTP的post方法。代码如下:

use App\Http\Resources\ProductResource;
use App\Models\Products;

public function store(Request $request)
{
        $product_name = $request->input('name');
        $product_price = $request->input('price');
        $product_description = $request->input('description');

        $product = Products::create([
            'name' => $product_name,
            'price' => $product_price,
            'description' => $product_description,
        ]);
        return response()->json([
            'data' => new ProductResource($product)
        ], 201);
}

Update(更新产品信息)

更新产品的名字、价格、描述信息,具体的逻辑代码如下:

use App\Http\Resources\ProductResource;
use App\Models\Products;

public function update(Request $request, Products $product)
{
        $product_name = $request->input('name');
        $product_price = $request->input('price');
        $product_description = $request->input('description');

        $product->update([
            'name' => $product_name,
            'price' => $product_price,
            'description' => $product_description,
        ]);
        return response()->json([
            'data' => new ProductResource($product)
        ], 200);
}

Destroy(删除一条产品记录)

如下代码所示:

use App\Models\Products;

public function destroy(Products $product)
{
   $product->delete();
   return response()->json(null,204);
}

Routes&EndPoints

下面创建EndPoints,这样就能进行HTTP访问了,在routes/api.php中新增如下代码:

//routes/api.php
<?php

use App\Http\Controllers\ProductsController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Route::get('products', [ProductsController::class, 'index'])->name('products.index');
Route::get('products/{product}', [ProductsController::class, 'show'])->name('products.show');
Route::post('products', [ProductsController::class, 'store'])->name('products.store');
Route::put('products/{product}', [ProductsController::class, 'update'])->name('products.update');
Route::delete('products/{product}', [ProductsController::class, 'destroy'])->name('products.destroy');

上面的Endpoints和ProductsController中方法是对应的。

下面测试下ProductsController中的index函数,是HTTP的Get请求,返回值如下:

[
    {
        "id": 1,
        "name": "quo",
        "price": 15,
        "description": "Ut rerum aut deleniti eveniet ad et ullam perferendis.",
        "created_at": "2022-11-18T15:18:13.000000Z",
        "updated_at": "2022-11-18T15:18:13.000000Z"
    },
    {
        "id": 2,
        "name": "maxime",
        "price": 70,
        "description": "Natus officiis repellat vero ea voluptatem mollitia similique.",
        "created_at": "2022-11-18T15:18:13.000000Z",
        "updated_at": "2022-11-18T15:18:13.000000Z"
    }
]

格式化响应

上面的响应是以Json格式返回的,内容包括了数据库中的所有列。

如果想返回指定的列。比如不需要返回created_at,update_at,以及关于商品打折的信息。所有就需要定制下响应。创建响应类:

php artisan make:resource ProductResource

改变下返回数组。

//App/Http/Resources/ProductResource
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class ProductResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'product_name' => $this->name,
            'product_price' => "$" . $this->price,
            'discounted_price' => "$" . ($this->price * 0.9),
            'discount' => "$" . ($this->price * 0.1),
            'product_description' => $this->description,
        ];
    }
}

再到ProductsController中index更新成如下代码:

public function index()
{
   return ProductResource::collection(Products::all());
}

返回新的响应内容如下:

{
    "data": [
        {
            "id": 1,
            "product_name": "quo",
            "product_price": "$15",
            "discounted_price": "$13.5",
            "discount": "$1.5",
            "product_description": "Ut rerum aut deleniti eveniet ad et ullam perferendis."
        },
{
            "id": 2,
            "product_name": "maxime",
            "product_price": "$70",
            "discounted_price": "$63",
            "discount": "$7",
            "product_description": "Natus officiis repellat vero ea voluptatem mollitia similique."
        }
    ]
}

Response Codes

每一个响应最好都带有一个序列。这样客户端可以知道当前服务端的状态。

一般的相应码如下:

  • 200-OK,响应正常;
  • 201-Created,通过在Post请求里面,代表资源创建成功;
  • 204-No Content,无数据返回,通常在删除资源的时候用;
  • 400-Bad Request,用户提交的密码或参数不正确;
  • 401-Unauthorized,用户无权限,需要身份验证;
  • 403-Forbidden,用户权限不够,禁止访问;
  • 404-Not Found,无对应的此资源;
  • 500-Internal Server Error,服务端内部错误。

Laravel使用jsonse->json()函数可以带个响应码。代码如下:

response->json(data,status code)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Laravel文档阅读笔记-How to Build a Rest API with Laravel: A Beginners Guide① 的相关文章

  • Laravel 登录后重定向回来

    登录后如何重定向返回页面 在 Laravel 5 2 中 认证控制器 protected redirectTo 重定向用户
  • 修复 laravel 5 会话在刷新或进入另一个页面后过期的问题?

    我正在使用 laravel 默认身份验证 当我登录我的网站时 一切都很好 当我尝试刷新或转到另一个页面 仍然使用身份验证中间件 时 我的会话已过期 我直接注销 必须再次登录 如何解决此问题 以便在刷新页面或浏览另一个页面时保持登录状态 值得
  • 此集合实例上不存在属性 [子类别]

    第一次与eloquent关系 我正在尝试访问subcategory method但我收到这个错误 此集合实例上不存在属性 子类别 Laravel 新手 因此任何帮助将不胜感激 blade table class table thead tr
  • 有没有什么好的工具可以查看和浏览ant构建文件?

    我发现很难读取 ant 构建文件 特别是如果构建文件包含大量导入文件 例如属性文件和其他 xml 构建文件 因此 我想知道是否有一些好的工具可以提供帮助 例如在 IDE 中查看和浏览源代码 提前致谢 Try 盛大 这里 http www g
  • 使用 Instagram Basic Display API 时出现“无效平台应用程序”错误

    我正在尝试使用 Instagram Basic 显示 API 但是当我发布授权代码以获取访问令牌时 我不断收到以下错误 error type OAuthException 代码 400 error message 平台应用无效 我正在遵循此
  • 如何将 Smarty 3 包含到 Laravel 4 中?

    我是 Laravel 的新手 所以仍在习惯这些概念 但是我有大约 10 年的使用 Smarty 的经验 所以我希望利用这一点 除了事实上 Blade 似乎缺乏太多我发现有用且在 Smarty 中开箱即用的功能 但无论如何除了这个问题的要点之
  • 如何从 Laravel 执行存储过程

    我需要在表单提交数据后执行存储过程 我让存储过程按照我想要的方式工作 并且我的表单正常工作 我只是不知道从 laravel 5 执行 sp 的语句 它应该是这样的 执行 my stored procedure 但我似乎在网上找不到类似的东西
  • Laravel 保存/更新多对多关系

    谁能帮助我如何保存多对多关系 我有任务 用户可以有很多任务 任务可以有很多用户 多对多 我想要实现的是更新表格管理员可以将多个用户分配给特定任务 这是通过 html 多选输入完成的 name taskParticipants 这里的问题是
  • Laravel 白名单域认证

    我正在寻找只允许某些域访问我的 laravel 应用程序的最佳方法 我目前正在使用 Laravel 5 1 并且如果引用域不在白名单域中 则使用中间件进行重定向 class Whitelist Handle an incoming requ
  • EPi服务器开发

    除了 Episerver com 之外 使用EPiServer开发的人还使用哪些其他网站作为开发资源 一直在使用 coderesort com 但我发现它缺乏如何做事的示例 非常感谢 J 我用于EPiServer开发的通用资源 EPi服务器
  • 简单、安全的API认证系统

    我有一个简单的 REST JSON API 供其他网站 应用程序访问我网站的一些数据库 通过 PHP 网关 基本上该服务的工作原理如下 调用 example com fruit orange 服务器返回有关橙子的 JSON 信息 问题是 我
  • rabbitmq 的 REST API

    有没有办法从 ajax 向 RabbitMQ 发送数据 我的应用程序由数千个 Web 客户端 用 js 编写 和 WCF REST 服务组成 现在我试图弄清楚如何为我的应用程序创建可扩展点 这个想法是有一个rabbitmq实例 它从放置在一
  • 向 Laravel 的 Mailer 添加新的传输驱动程序

    我需要向 Laravel 的邮件包添加一个新的传输驱动程序 以便我可以通过默认情况下不支持的外部服务 Mailjet 发送电子邮件 编写传输驱动程序不会成为问题 但我找不到一种方法来连接并添加新的驱动程序 以便我可以继续正常使用 Larav
  • Laravel 中的高级 whereNotNull 语句

    在 Laravel 4 中可以执行以下操作吗 DB table myTable gt select DB raw columnNames gt whereNotNull function query use columns foreach
  • Laravel-5 如何使用 id 值和名称值从数据库填充选择框

    我想创建一个如下所示的选择框照亮 html https github com illuminate html
  • Laravel snappy 返回无法加载 about:blank,网络状态代码 301 和 http 状态代码 0 - 协议“about”未知错误

    我正在使用基于 wkhtmltopdf 的 laravel snappy 一切正常 但现在在服务器和本地我收到此错误 无法加载 about blank 网络状态代码 301 和 http 状态代码 0 协议 about 未知错误 和 阻止访
  • 由 aws API 制作的 HttpRequest 拦截器

    我正在开发一个项目 该项目使用 cognito 作为身份验证服务来保护使用 nodeJS 制作的无服务器休息 API 我已成功关闭未经身份验证的客户端的 API 现在 每当我从 Angular 客户端发出请求时 我都需要在标头中自动注入一个
  • 重命名猫鼬中的字段[重复]

    这个问题在这里已经有答案了 我有两个 JSON 对象 每个对象都有一个名字字段 我想将名字重命名为名称 还想使用猫鼬将现有的名字值导入到名称 Schema const mongoose require mongoose const Sche
  • 从 WCF REST 获取错误详细信息

    我有一个由 Net WCF 客户端使用的 REST 服务 遇到错误时 REST 服务会返回 HTTP 400 错误请求 响应正文包含 JSON 序列化详细信息 如果我使用 Fiddler Javascript 或直接从 C 执行请求 我可以
  • SQLAPI++ 的免费替代品? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有任何免费 也许是开源 的替代品SQLAPI http www sqlapi com 这个库看起来

随机推荐

  • 关于manjaro命令行界面方块乱码

    通常情况下这些方块乱码是中文 xff0c 其实这篇文档讲的很清楚 xff0c 如果 etc locale conf中有设置LANG 61 zh CN UTF 8就会导致tty乱码 解决办法也如文档所说有两个 xff1a 首先是修改 etc
  • 如何安装arm交叉工具链及问题解决

    在进行基于arm的嵌入式linux开发时 xff0c 首先要安装交叉工具链 要按照交叉工具链首先要获得交叉工具链的压缩包 xff0c 我这里用的是开发板上自带的压缩包 xff1a arm linux gcc 4 5 1 v6 vfp tgz
  • 04)go语言使用优化 启动时不打开CMD控制台,后台运行

    一 生成没有cmd窗口的exe程序 1 目前go语言生成exe我是在goland运行时设置了输出路径 xff0c 运行时就会产生exe可执行文件 2 默认是执行的go bulid指令 xff0c 生成的ext双击打开是有CMD窗口的 xff
  • C#使用RDP远程桌面

    由于本人是做数据库维护经常使用到远程桌面 xff0c 但是windows自带的远程桌面难以区分很不方便 xff0c 所以我自己写了一个RDP RDP一共修改了两次 第一种思路就是使用windows自带的RDP xff0c 保存成RDP文件
  • 【Altium秘籍】room 复制报错的解决办法

    在使用多通道绘图时 nbsp 有时会出现 nbsp 后加的通道 无法拷贝room格式 nbsp 仔细看会发现 是由于新建的 room 不属于原来的 类中 这个原因 个人觉得是 软件的bug nbsp 更新数据时遗漏导致 数据不同步 目前 n
  • 将多边形点按照逆时针排序

    Point center bool PointCmp const Point amp a const Point amp b if a x gt 61 0 amp amp b x lt 0 return true if a x 61 61
  • 排队论入门学习 (for 数学建模)

    排队论入门学习 xff08 for 数学建模 xff09 文字部分引用了很多浙大数学建模排队论ppt中的内容 xff0c 本人做个总结和代码实现 为什么研究排队论 xff1f 研究排队问题 xff0c 就是要把排队的时间控制到一定的程度内
  • 层次分析法(AHP)

    层次分析法 xff08 AHP xff09 问题的提出 日常生活中有许多决策问题 决策是指在面临多种方案时需要依据一定的标准选择某一种方案 购物 xff1a 买钢笔 xff0c 一般要依据质量 颜色 实用性 价格等方面的因素来选择某一只钢笔
  • 遗传算法解决TSP问题(c++实现)

    遗传算法 遗传算法简介 遗传算法 Genetic Algorithms xff0c 简称 GA 是一种基于自然选择原理和自然遗传机制的搜索 寻优 算法 xff0c 它是模拟自然界中的生命进化机制 xff0c 在人工系统中实现特定目标的优化
  • 灰色预测模型GM(1,1) 与例题分析

    灰色预测模型 灰色预测的概念 xff08 1 xff09 灰色系统 白色系统和黑色系统 白色系统是指一个系统的内部特征是完全已知的 xff0c 既系统信息是完全充分的 黑色系统是一个系统的内部信息对外界来说是一无所知的 xff0c 只能通过
  • 共轭梯度法的推导与完整算法

    共轭梯度法 学习自知乎 xff1a https www zhihu com question 27157047 and wikipedia and 非线性规划课 简介 在数值线性代数中 xff0c 共轭梯度法是一种求解对称正定线性方程组Ax
  • 随机森林算法学习(RandomForest)

    随机森林算法学习 最近在做kaggle的时候 xff0c 发现随机森林这个算法在分类问题上效果十分的好 xff0c 大多数情况下效果远要比svm xff0c log回归 xff0c knn等算法效果好 因此想琢磨琢磨这个算法的原理 要学随机
  • 锁存器芯片74HC573芯片的用法,及其在实际电路中的应用

    一 74HC573介绍 锁存器是一种对脉冲电平敏感的存储单元电路 xff0c 它们可以在特定输入脉冲电平作用下改变状态 锁存 xff0c 就是把信号暂存以维持某种电平状态 锁存器的最主要作用是缓存 xff0c 其次完成高速的控制器与慢速的外
  • 与信息熵相关的概念梳理(条件熵/互信息/相对熵/交叉熵)

    香农信息量 信息量表示不确定性的大小 信息量的单位是比特 xff08 bit xff09 香 农 信 息 量 61 log
  • 农业领域的知识图谱构建(Agriculture_KnowledgeGraph)

    Agriculture KnowledgeGraph demo xff1a http ecnukg vicp io github xff1a https github com qq547276542 Agriculture Knowledg
  • vue使用axios给echarts渲染数据不展示的解决方法;

    因为自己遇到了所以分享下解决办法 xff0c 也记一下笔记 xff1b 第一步 xff1a 1 这里首先引入Echarts组件 lt template gt lt div gt lt Echart options 61 34 options
  • 银河麒麟PyCharm中文设置

    银河麒麟自带的PyCharm xff08 社区版 xff09 可以设置成中文 xff0c 直接上图 在File Settings 在Plugins搜索 Chinese xff0c 下载安装后 xff0c 重启PyCharm xff0c 变成
  • Linux环境Nacos、SpringBoot项目jar包启动慢

    问题描述 xff1a 本地开发环境 测试环境服务可以正常启动 生产环境Nacos启动需要好几分钟 xff0c springboot项目启动前2分钟无日志输出 xff0c 启动时连接Nacos报错 Client not connected c
  • Python文档阅读笔记-Turn Images into Cartoons using Python

    本博文说明如何将图片转为卡通风格 1 导入依赖模块 在编程的第一步首先要导入依赖库 xff0c 在这个图像转换成卡通风格的程序中需要包含3个模块 xff0c 分别是openCV xff0c numpy xff0c matpoltlib im
  • Laravel文档阅读笔记-How to Build a Rest API with Laravel: A Beginners Guide①

    随着移动端和JavaScript框架的发展 xff0c 比如React和Vue xff0c Restful风格的API越来越流行 使用Restful风格的好处就是一个后端程序可以与多个版本的前端用户界面关联 Laravel提供了创建Rest