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

news2024/11/29 10:56:57

 

随着移动端和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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/166175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL中给字符串字段加索引

文章目录前言一、前缀索引和普通索引二、前缀索引对覆盖索引的影响三、优化前缀索引前言 学完了MySQL索引部分&#xff0c;我们清楚的认识到给子段添加索引可以快速的进行查询&#xff0c;节约时间。但是索引有很多。那么对于字段怎么加索引&#xff0c;加什么索引。加到索引不…

linux基本功系列之useradd命令实战

文章目录一. useradd 命令介绍二. 语法格式及常用选项三. 参考案例3.1 不加任何参数创建用户3.2 创建不能登录系统且没有家目录的用户3.3 创建一个用户&#xff0c;ID为23333.4 创建一个用户并指定其附加组3.5 创建用户并账户过期时间3.6 与useradd相关的目录文件总结前言&…

InfluxDB的查询优化

首先&#xff0c;在学习influxDB的查询优化之前&#xff0c;我们要先学习下InfluxDB的解释器profiler&#xff08;类似于mysql的Explain语句&#xff0c;不一样的是&#xff0c;sql&#xff0c;hivesql是提前查看执行计划等&#xff0c;Influx是在当前查询的最后一页两张表&…

力扣(LeetCode)382. 链表随机节点(2023.01.15)

给你一个单链表&#xff0c;随机选择链表的一个节点&#xff0c;并返回相应的节点值。每个节点 被选中的概率一样 。 实现 Solution 类&#xff1a; Solution(ListNode head) 使用整数数组初始化对象。 int getRandom() 从链表中随机选择一个节点并返回该节点的值。链表中所有…

WhatsApp居然有3个版本?深度详解区别!外贸圈获客神器用起来!

近两年&#xff0c;外贸圈用WhatsApp来营销获客&#xff0c;越来越火。不少走在前头的外贸人&#xff0c;已经尝到了甜头。但也有不少后来者&#xff0c;站在门外张望的时候&#xff0c;整个人都是蒙圈的。❓听说动不动要整几十个账号&#xff0c;还要花老长时间养号&#xff1…

《Linux Shell脚本攻略》学习笔记-第六章

6.1 简介 你开发应用程序的时间越长&#xff0c;就越能体会到有一个能够跟踪程序修订历史的软件是多重要。 大多数Linux发行版中都包含了Git。如果你的系统中还没有安装&#xff0c;可以通过yum或者apt-get获取。 6.2 创建新的git仓库 git中的所有项目都需要有一个用于保存项目…

MyBatis-Plus字段加密解密

项目创建POM依赖 <dependency><!--MyBatis-Plus 企业级模块--><groupId>com.baomidou</groupId><artifactId>mybatis-mate-starter</artifactId><version>1.2.8</version> </dependency> <!-- https://mvnrepository…

规划之路:SLAM学习经验分享

针对想学SLAM的提问&#xff0c;我觉得我还是有一定的发言权。作为一个刚入坑SLAM一年多的初学者&#xff0c;首先想说的就是这个研究方向比较广&#xff0c;大方向按搭载传感器分为激光SLAM和视觉SLAM两种&#xff0c;激光SLAM搭载激光雷达&#xff0c;视觉SLAM搭载单目、双目…

[NSSRound#6 Team]Web学习

[NSSRound#6 Team]Web学习 文章目录[NSSRound#6 Team]Web学习前言一、[NSSRound#6 Team]check(V1)二、[NSSRound#6 Team]check(Revenge)总结前言 日常做点题娱乐下&#xff0c;刷到了[NSSRound#6 Team]中是三道web题&#xff0c;学习到了不少&#xff0c;记录下知识点。 提示&…

C语言综合练习6:制作贪吃蛇

1 初始化界面 因为还没学QT&#xff0c;我们就使用终端界面替代。 这里我们假设界面中没有障碍物&#xff0c;我们只需要设定界面的高宽就行&#xff0c;这是蛇的移动范围&#xff0c;我们可以写两个宏来规定界面的高宽 新建一个snake.c的文件 #define _CRT_SECURE_NO_WARNIN…

快出数量级的性能是怎样炼成的

前言&#xff1a;今天学长跟大家讲讲《快出数量级的性能是怎样炼成的》&#xff0c;废话不多说&#xff0c;直接上干货~我们之前做过一些性能优化的案例&#xff0c;不算很多&#xff0c;还没有失手过。少则提速数倍&#xff0c;多则数十倍&#xff0c;极端情况还有提速上千倍的…

关于IDEA配置本地tomcat部署项目找不到项目工件的问题解答

文章目录一 原因分析二 解决方案三 具体的操作方法3.1 打开项目结构找到工件3.2 添加具体的工件内容3.3 配置本地tomcat一 原因分析 可能是之前的项目再次打开后&#xff0c;没有及时配置项目结构中的工件信息&#xff0c;导致配置tomcat中看不到工件的信息 二 解决方案 解决…

react组件优化,当父组件数据变化与子组件无关时,控制子组件不重新渲染

首先 我们来建立一个场景 我们创建一个react项目 然后创建一个父组件 这里我要叫 record.jsx 参考代码如下 import React from "react"; import Subset from "./subset";export default class record extends React.Component{constructor(props){super(…

工作的同时,我也在这里做副业

文章目录一、什么是独自开&#xff1f;二、独自开能给我们带来什么利益&#xff1f;三、如何使用独自开&#xff1f;3.1、用户任务报价步骤13.2、用户任务报价步骤2四、未来的愿景一、什么是独自开&#xff1f; 独自开&#xff0c;全称独自开发一套系统&#xff0c;是基于商品…

CTP开发(2)行情模块的开发

我在做CTP开发之前&#xff0c;也参考了不少其他的资料&#xff0c;发现他们都是把行情和交易做在同一个工程里的。我呢之前也做过期货相关的交易平台&#xff0c;感觉这种把行情和交易做在一起的方法缺乏可扩展性。比如我开了多个CTP账户&#xff0c;要同时交易&#xff0c;这…

springMVC的学习拦截器之验证用户登录案例

文章目录实现思路关于环境和配置文件pomspring的配置文件关于idea的通病/常见500错误的避坑实现步骤编写登陆页面编写Controller处理请求编写登录成功的页面编写登录拦截器实现思路 有一个登录页面&#xff0c;需要写一个controller访问页面登陆页面提供填写用户名和密码的表单…

UE4c++日记1(允许 创类、蓝图读写/调用/只读、分类、输出日志打印语句)

目录 1允许创建基于xx的蓝图类 2允许蓝图读写/允许蓝图调用/只读 读写调用 只读 3为变量/函数分类 4输出日志打印一段话 1.先创建一个蓝图类 2.构建对象 3.写提示代码&#xff0c;生成解决方案 4.运行&#xff0c;打开“输出日志” 5.总结 创类-实例化对象&#xff08;构建…

2022年个人年终总结(一)

2022年个人年终总结&#xff08;一&#xff09;考研想法的萌生回顾过去一年-考研心路历程基础阶段&#xff08;1-6月&#xff09;强化阶段&#xff08;7-9月&#xff09;冲刺阶段&#xff08;10-12月&#xff09;感受总结特别感谢2022年是做梦的一年&#xff0c;花了一年的时间…

Zookeeper相关操作

Zookeeper概念 •Zookeeper 是 Apache Hadoop 项目下的一个子项目&#xff0c;是一个树形目录服务。 •Zookeeper 翻译过来就是 动物园管理员&#xff0c;他是用来管 Hadoop&#xff08;大象&#xff09;、Hive(蜜蜂)、Pig(小 猪)的管理员。简称zk •Zookeeper 是一个分布式的…

【C++】非递归实现二叉树的前中后序遍历

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;二叉树的…