TubeSum ← Transcribe a video

How to Build a REST API With Laravel: PHP Full Course

Transcribed Jun 15, 2026 Watch on YouTube ↗
Intermediate 55 min read For: PHP developers with basic Laravel knowledge who want to learn how to build RESTful APIs.
342.6K
Views
6.7K
Likes
309
Comments
67
Dislikes
2.0%
📊 Average

AI Summary

This course teaches how to build a RESTful API using Laravel, covering everything from setup and data modeling to authentication with Laravel Sanctum. The instructor guides through creating models, migrations, controllers, and implementing features like filtering, sorting, bulk inserts, and token-based authorization.

[00:41]
Course Overview

The course covers building a RESTful API from scratch, including data models, seeding, GET requests, JSON transformation, filtering, validation, bulk inserts, and authentication with Laravel Sanctum.

[01:44]
Prerequisites and Setup

Requirements: PHP, HTTP server, database (MySQL or compatible), and Laravel. Options include Docker, XAMPP, or manual setup with Composer.

[07:41]
Creating Models and Migrations

Use Artisan to create models, migrations, factories, seeders, and controllers for Customer and Invoice with a one-to-many relationship.

[19:28]
API Versioning

Version APIs by segregating controllers into version folders (e.g., v1) and using route groups with prefixes to maintain backward compatibility.

[26:22]
Resource Classes for JSON Transformation

Use Laravel resources to transform model data into JSON, converting snake_case to camelCase and hiding fields like timestamps.

[35:54]
Filtering and Querying

Implement a reusable filter system using query string parameters with bracket notation for operators (e.g., `postalCode[gt]=30000`).

[58:54]
Including Related Data

Allow clients to include related data (e.g., invoices with customers) via query parameter `includeInvoices=true`, using conditional loading in resources.

[65:42]
Creating and Updating Resources

Use form request classes for validation, handle PUT (full replacement) and PATCH (partial update) requests, and transform camelCase input to snake_case for storage.

[82:56]
Bulk Insert

Implement a bulk store endpoint for invoices, validating an array of objects and using the `insert` method for efficient batch insertion.

[93:46]
Authentication with Laravel Sanctum

Sanctum provides token-based authentication. Tokens can have abilities (e.g., create, update) for authorization. If no abilities are specified, the token has full access.

Laravel provides powerful tools like resources, form requests, and Sanctum to build secure, scalable RESTful APIs efficiently. The course demonstrates a practical approach to API development with reusable components and best practices.

Clickbait Check

95% Legit

"The title accurately describes the full course content; it's a comprehensive tutorial on building a REST API with Laravel."

Mentioned in this Video

Tutorial Checklist

1 01:44 Set up development environment: install PHP, HTTP server, database, and Laravel via Docker, XAMPP, or Composer.
2 07:41 Create models, migrations, factories, seeders, and controllers using Artisan: `php artisan make:model Customer -a` and `php artisan make:model Invoice -a`.
3 07:41 Define database schema in migration files: add columns for customers (name, type, email, address, city, state, postal_code) and invoices (customer_id, amount, status, billed_date, paid_date).
4 12:27 Define factories to generate test data: use Faker to create realistic customer and invoice data.
5 16:15 Seed the database: run `php artisan migrate:fresh --seed` to create tables and populate with test data.
6 19:28 Set up API versioning: create version folders (e.g., `Controllers/API/v1`), update namespaces, and define routes in `routes/api.php` using route groups with prefix and namespace.
7 26:22 Create resource classes for JSON transformation: use `php artisan make:resource V1/CustomerResource` and `CustomerCollection` to convert snake_case to camelCase and hide timestamps.
8 35:54 Implement filtering: create a base `ApiFilter` class and extend it for customers and invoices, allowing query string parameters like `postalCode[gt]=30000`.
9 58:54 Add support for including related data: use `whenLoaded` in resources and check query parameter `includeInvoices` to conditionally load invoices.
10 65:42 Create form request classes for validation: `php artisan make:request V1/StoreCustomerRequest` and `UpdateCustomerRequest`, define rules, and handle PUT/PATCH differences.
11 82:56 Implement bulk insert: add a route `invoices/bulk` and a `bulkStore` method in InvoiceController, validate array of objects, and use `Invoice::insert($data)`.
12 93:46 Install and configure Laravel Sanctum: publish config, run migration, and protect API routes with `auth:sanctum` middleware.
13 101:35 Implement token abilities: use `tokenCan()` in form request authorize methods to check for 'create' or 'update' capabilities.

Study Flashcards (10)

What is the purpose of Laravel resource classes?

easy Click to reveal answer

To transform Eloquent models into JSON responses with control over the output format.

27:28

How do you convert snake_case database columns to camelCase in JSON responses?

medium Click to reveal answer

In the resource's `toArray` method, use camelCase keys and map them to the model's snake_case attributes.

30:51

What is the difference between PUT and PATCH requests in REST APIs?

easy Click to reveal answer

PUT replaces the entire entity (all fields required), while PATCH updates only the provided fields.

75:09

How do you validate an array of objects in a Laravel form request?

hard Click to reveal answer

Use asterisk dot notation: `*.customer_id` for each property in the rules array.

85:48

What happens if you create a Sanctum token without specifying abilities?

medium Click to reveal answer

The token gets all abilities (represented by an asterisk in the database).

105:28

How do you check if a Sanctum token has a specific ability?

medium Click to reveal answer

Use the `tokenCan('ability')` method on the authenticated user object.

102:43

What is the command to create a model with migration, factory, seeder, and controller?

easy Click to reveal answer

`php artisan make:model ModelName -a`

08:14

How do you include related data conditionally in a resource response?

medium Click to reveal answer

Use the `whenLoaded('relation')` method in the resource's `toArray`.

63:25

What is the purpose of the `prepareForValidation` method in a form request?

hard Click to reveal answer

To modify or merge input data before validation runs, e.g., converting camelCase to snake_case.

70:17

How do you paginate results in a Laravel API resource collection?

easy Click to reveal answer

Call `paginate()` on the query builder and pass the result to the collection resource.

33:11

💡 Key Takeaways

⚖️

API Versioning Importance

Explains why versioning is critical for maintaining backward compatibility with API consumers.

19:28
🔧

Resource Classes for JSON Control

Demonstrates how to transform database columns to camelCase and hide fields, a common API requirement.

27:28
🔧

Reusable Filter System

Shows a flexible, reusable filtering mechanism using query strings with operators, avoiding complex parsing.

35:54
📊

Sanctum Token Abilities

Highlights that tokens without explicit abilities get full access, a crucial security nuance.

93:46
💡

Token Ability Default Behavior

Reveals that omitting abilities grants all permissions, which can be a security risk if not handled.

105:28

✂️ Creator Tools: Viral Hooks

AI-generated clip ideas for Shorts based on the transcript

Why Laravel for REST APIs?

45s

Quickly hooks developers by addressing the pain of building APIs and promising a solution with Laravel.

▶ Play Clip

Don't Over-Engineer Your API

60s

Offers a contrarian, experience-based take that resonates with developers tired of feature bloat.

▶ Play Clip

[00:00] [MUSIC]

[00:10] Building a restful API can be a daunting

[00:15] that you need to consider.

[00:16] For one, you need a suitable framework

[00:21] But it also needs to provide built in

[00:25] that you can go from development to

[00:29] of time.

[00:30] And Laravel has got you covered.

[00:32] Hi, I am Jeremy MCPeak with Tuts+.

[00:35] And I invite you to join me so

[00:37] that I can teach you how to build

[00:41] We'll start from scratch by

[00:44] seeding our database with test data.

[00:47] We'll then dive right into developing

[00:52] And you'll learn how to transform the data

[00:57] conventional JSON format.

[00:59] You'll then learn how

[01:01] reusable filter syntax so that end

[01:06] From there, you'll learn how to handle and

[01:09] validate manipulative requests

[01:14] We'll also discuss how to implement

[01:18] that end users can quickly insert

[01:23] We'll then look at how to protect your

[01:27] And how you can use its token

[01:31] authenticate requests but

[01:36] We have a lot of ground to cover,

[01:39] [MUSIC]

[01:44] Of course, the first thing that we need to

[01:47] that you need to follow along.

[01:48] And the list is relatively short, but

[01:51] there's a variety of ways that you can

[01:55] You need PHP, you need an HTTP server,

[01:59] preferably MySQL or something compatible.

[02:01] And then you of course need Laravel.

[02:04] Now, the one solution that's going to give

[02:11] If you're not familiar with Docker,

[02:14] It's not a virtual machine,

[02:18] know kinda sounds like I'm splitting hairs

[02:22] Docker is for

[02:26] that you can run applications regardless

[02:30] and that's all it is.

[02:32] A virtual machine is for setting up CPU,

[02:37] But that's getting off into the weeds.

[02:38] So if you go to laravel.com,

[02:42] then click on your first Laravel project.

[02:45] And it's going to kind of walk you through

[02:49] Regardless of what operating system

[02:53] this is an option for you.

[02:55] However, for Windows,

[02:56] it's a little bit more involved because

[03:01] Linux version 2 and enable that and get

[03:06] And when it comes to development

[03:09] virtualization because it completely

[03:13] from your main machine.

[03:14] However, this particular machine

[03:18] which prevent me from using Docker.

[03:20] So instead, I'm going to use

[03:25] This is an all in one solution

[03:30] So this will give you PHP,

[03:34] MariaDB which is a MySQL Clone and Perl.

[03:38] And one of the things that I really

[03:41] no configuration.

[03:42] And so by downloading and installing

[03:46] configured.

[03:47] And that is a very nice thing because

[03:52] you have to configure everything manually.

[03:55] But that's not it, you also get a nice

[03:59] that you can turn these services on and

[04:02] And of course, using something like XAMPP

[04:07] it says on the screen here.

[04:08] There are other tools that are built

[04:13] a database like PHP,

[04:17] So this is a very nice

[04:20] Now, if you're going to take this route or

[04:23] if you are going to install and

[04:28] then you will need to install Laravel,

[04:32] The website is getcomposer.org, and

[04:36] basically it is a very easy thing

[04:41] And then from there you just need

[04:46] type this out,

[04:51] And this is going to download and

[04:55] that you can create new projects on

[04:59] And to do that, simply type laravel new,

[05:05] We'll call this laravel-api.

[05:07] This will take a few moments to

[05:11] But once that's done we can start

[05:16] with our database.

[05:17] The installer creates a new directory

[05:21] So the first thing you want to do

[05:25] And we'll go ahead and fire up

[05:29] modify the environment file that contains

[05:34] Now, in my case,

[05:35] everything is already set up because

[05:40] If you are using something like XAMPP or

[05:44] tool, then chances are you won't

[05:47] If you manually set up your environment

[05:53] make some changes.

[05:54] If you're using the Docker image then

[05:59] you, so you don't have to do anything.

[06:01] Now, in my case,

[06:04] And we can change the name of

[06:08] I typically named the databases

[06:12] That just makes things a little bit

[06:15] So you can name your database

[06:19] do be sure that your connection

[06:22] For me it is, so all I need to do

[06:27] I need to start up the MySQL database,

[06:30] which is actually a Maria database,

[06:35] And really, this is the only thing that

[06:40] You could use the command line for

[06:42] the database if you wanted

[06:45] However, when it comes to working with

[06:49] So I'm going to use what is given to

[06:54] And I am simply going to click on New,

[06:58] creating a new database.

[07:00] It shows you the databases that

[07:04] in and system databases, so

[07:09] But as far as the database name I'm

[07:13] to create and

[07:17] So that now whenever we use artisan

[07:21] that it's going to connect to that

[07:25] So in the next lesson,

[07:28] We are going to create our models and

[07:31] the data that we are going to be working

[07:36] [MUSIC]

[07:41] In this lesson we are going to do much

[07:44] We are going to create the migrations,

[07:46] the factories ,the cedars

[07:49] And of course,

[07:52] some of that is going

[07:54] And now we are going to take a smaller

[07:59] are just working with

[08:02] Such as customers and invoices that

[08:08] So, let's get started by using artisan

[08:14] and we're going to use the all flag.

[08:16] This is going to create well just about

[08:21] type of data, and then we will do

[08:26] The relationship between these two types

[08:31] one customer can have many invoices.

[08:33] So, the first thing I want

[08:37] open up our models so

[08:41] So, let's go to app,

[08:44] we're going to add in our

[08:47] So, this will be just

[08:51] where we will return the HasMany, and

[08:57] And then for the invoice class we will

[09:01] So, really let's just copy this so

[09:06] then make the necessary changes.

[09:08] So, the inverse of

[09:12] our class is of course going

[09:17] the name of our method

[09:21] And that's all we're going to do

[09:25] We're going to focus more

[09:28] everything else as far as

[09:31] So, let's go to the Database folder,

[09:35] we'll start with

[09:38] In a real application there is

[09:43] individual customer.

[09:44] And I don't think we need

[09:48] I want a lot of data to just work with.

[09:50] So, we're gonna have quite a few columns

[09:55] the customer, and then we're gonna

[09:59] Now, the idea behind the type is that

[10:04] or it could be a business.

[10:06] So, this is just going to be a column that

[10:11] i for individual and a b for business.

[10:14] And of course we would need some kind of

[10:19] that we interact with.

[10:21] And then it will be helpful to

[10:25] postal code, so let's go ahead and

[10:30] And that's all that we are going to

[10:33] Now of course, we could add a whole lot

[10:37] So, now let's go to the invoice and

[10:43] Now, the very first thing that we need

[10:46] other than the id is the foreign key for

[10:51] But then it would also be useful to

[10:55] let's just keep that as an integer.

[10:58] Ideally, we would have more

[11:01] the most part,

[11:04] that's really all that we care about

[11:09] And then we will have a status,

[11:12] this is going to be somewhat similar

[11:16] in that it will typically

[11:20] Now, let's say that we could have a build,

[11:25] build the customer for this invoice.

[11:27] We will have a paid signifying that

[11:31] then there will be a void because

[11:35] we need to void that invoice.

[11:37] Now, it would be useful to have

[11:43] like if it is billed,

[11:47] if it is paid,

[11:51] Now, both of these of course

[11:54] so let's go ahead and specify that.

[11:56] But an invoice might not be paid, in which

[12:01] so let's mark this as mullable, and

[12:06] And of course there's also a whole lot

[12:10] an invoice.

[12:11] And ideally, we would have another table

[12:16] that invoice but we're not going

[12:20] But of course having tables isn't enough,

[12:25] so let's work on our factories.

[12:27] So, let's open up our

[12:30] as far as the definition that

[12:33] Now, names are going to be, well, they

[12:39] it doesn't make sense to

[12:43] a company or a company's name for

[12:46] So, really what we need to do first of

[12:51] that is going to be created is going to

[12:56] So, we will use the random element method,

[13:01] our array is going to have simply I and

[13:04] b, of course for

[13:09] And then from there we can determine what

[13:13] going to be.

[13:15] So, if the type is equal to an I, then we

[13:21] because that is going to give

[13:27] Otherwise, we have a business,

[13:29] in which case we want to use the company

[13:34] And then we can use that value for

[13:38] we'll go ahead and set that value as well.

[13:41] And then for the email,

[13:46] the email would be somewhat related to the

[13:51] but we'll just use faker

[13:54] And then for address, city and state,

[13:57] we will use fakers methods

[14:00] So, with our CustomerFactory defined,

[14:06] and the first thing we will

[14:10] Now, one thing that we can do here is to

[14:16] come from the CustomerFactory, in which

[14:22] And then for the amount,

[14:26] it will be useful to have something that

[14:31] So, we're going to use

[14:37] between let's say 100 and 20000.

[14:41] Man, I would like to be able

[14:45] then we need the status.

[14:47] Now, the status can be one of three

[14:53] And really the next two fields,

[14:57] the paid date depend upon this status.

[15:01] So, let's kind of do the same thing

[15:04] get the status.

[15:05] Where we will use faker to once

[15:10] from an array that contains our statuses.

[15:14] So, we have build, we have paid,

[15:18] And then for the build date,

[15:23] what it is because we will

[15:28] So, we will go ahead and

[15:33] value that is going to be

[15:36] And really the dates don't matter,

[15:41] However, we do want something

[15:44] Now, one thing that we probably should do,

[15:50] then base the paid date off of

[15:55] so we do need to check that here.

[15:58] And if it is paid,

[16:02] you know let's just do this,

[16:07] Method, and if it is not paid,

[16:11] And now that we have our factories,

[16:15] So let's close our factories,

[16:19] let's open up CustomerSeeder and

[16:23] And really, the DatabaseSeeder as well,

[16:26] And now that I think about it, I don't

[16:30] because we can create everything

[16:34] because this is exactly what we could do.

[16:36] Let's, first of all,

[16:40] And let's say that we want at least 25

[16:48] I mean, we could be just lazy and

[16:52] they each have 10 invoices,

[16:55] Let's have a different number of

[17:00] So we're gonna use our factory,

[17:04] Each of them will have 25 invoices,

[17:09] So let's just copy and paste, so

[17:12] that then we can have 100 customers

[17:17] then we can create another 100

[17:23] And then finally, let's create some

[17:28] and let's make this a small amount.

[17:30] So five customers will not

[17:34] they will just be in our system.

[17:36] So with that in place,

[17:41] inside of the run method, we are going to

[17:47] So that's now we should be able to

[17:52] we will use artisan to migrate.

[17:55] Let's use fresh, and

[17:59] So if we typed everything correctly,

[18:04] so we cannot find the CustomerSeeder,

[18:10] inside of the CustomerSeeder, which,

[18:15] So let's use App\Models\Customer.

[18:19] Let's go back to the command line.

[18:21] Let's run the fresh migration again.

[18:23] Another error, and it looks like

[18:29] What was that file that

[18:32] So let's open up the customer factory and

[18:38] There we go.

[18:39] Let's go back.

[18:40] Let's run the seeder again, and

[18:46] column not found,

[18:50] So let's go to the migration and

[18:57] That was inside of invoice.

[18:58] So we have billed_dated,

[19:03] typing and talking at the same time.

[19:07] It's not that easy,

[19:10] So now, finally, hooray, everything works.

[19:14] We have our stuff.

[19:16] And so now that we have all

[19:19] we can start developing our

[19:22] [MUSIC]

[19:28] APIs are software.

[19:29] They are a specialized kind of software.

[19:32] But ultimately, they are software, we

[19:37] and then we decide to add new features,

[19:42] However, our users are developers, they

[19:47] And anything that we change

[19:52] So unlike conventional applications,

[19:58] So that as we release new versions,

[20:02] they're functioning.

[20:03] And developers who are using those old

[20:08] in the new versions, or they can

[20:13] So unfortunately, this means that

[20:16] of all of the different versions, but we

[20:21] But that's just the nature

[20:25] So one of the easiest ways to do this is

[20:30] need for different diversions, and the

[20:36] because those are what

[20:39] So this is what I typically do.

[20:41] Inside of the controllers folder, I will

[20:44] The idea being that this is the folder

[20:50] This is especially useful if you have

[20:55] application that is serving HTML, but

[20:57] you also have an API that

[21:01] And then inside of the API folder, this is

[21:07] So this is our first version,

[21:11] And then we will put inside of

[21:15] such as the customer controller and

[21:19] So let's go ahead and

[21:22] And of course, we need to do more than

[21:27] change their namespaces, otherwise we're

[21:31] So now, the namespaces for

[21:35] invoice controllers are app HTTP

[21:42] And we need to make that change on both

[21:47] But this is also going to change the

[21:52] we need to import that controller.

[21:55] So that's easy enough to do.

[21:57] We'll just import App\ http\Controllers,

[22:03] And of course,

[22:06] So any controller that we

[22:11] need to make those changes.

[22:13] And let's go ahead and

[22:15] at least implement the customer

[22:20] then simply return all of the customers

[22:25] Now, we could take this a step further and

[22:30] because we could make

[22:33] However, those changes

[22:37] as opposed to changing the columns

[22:40] So from that aspect, versioning your

[22:46] Actually it's a lot less common, but

[22:50] Now, of course, we need to set up

[22:54] So let's go to the API

[22:58] this is where we define the routes or

[23:01] And we want to include

[23:05] because every version

[23:08] And if you define a route inside of the

[23:15] So we would want then our version,

[23:20] and then our endpoints, such as customers,

[23:27] So one of the easiest ways to

[23:31] And there are several options

[23:34] The first is going to be the prefix, and

[23:37] we can simply set the prefix to

[23:42] So this is the first version.

[23:43] So the prefix will be v1.

[23:46] That is going to append to

[23:52] So we will have API/v1.

[23:55] But we can also make our lives

[24:00] the namespace, because all of our

[24:05] namespace, and that is simply

[24:10] Then Api, and then V1.

[24:12] And then from there,

[24:15] Now, we essentially have

[24:18] However, these are a little bit

[24:22] We don't really need to Create or

[24:27] So we can use the API resource method.

[24:31] It essentially gives us the same thing,

[24:35] Edit endpoints, so

[24:40] So we have customers and we would want to

[24:46] And then we will essentially do

[24:50] except we of course want the URL to

[24:55] invoice controller, and

[25:00] Okay, so with that in place,

[25:05] at least hit the index route

[25:09] So you of course need your

[25:11] And I'm using Firefox because

[25:15] it will automatically parse it into

[25:20] Well, it's more than halfway readable,

[25:23] So our URL is going to

[25:28] and we should see the output,

[25:33] As I said, this is very readable.

[25:35] We can go through this, and

[25:40] 225 or 250 users, we could do that.

[25:44] Now, as you'll notice,

[25:48] except when you get to the fields like

[25:54] Instead of using underscores, we would

[25:59] is the convention for the JSON format,

[26:04] of whatever language or

[26:07] And so in the next lesson,

[26:09] we are going to look at doing just that,

[26:13] because we don't need to supply

[26:18] [MUSIC]

[26:22] We ended the previous session

[26:25] And there's a lot to say about code that

[26:30] that doesn't.

[26:31] And all we are doing is returning all

[26:35] whenever we go to the customers endpoint.

[26:37] And there are some things that I

[26:42] example, the postal_code property.

[26:44] Now, for PHP and MySQL, that's perfectly

[26:50] especially for MySQL columns.

[26:52] However, now we are talking about JSON,

[26:55] the convention in JSON

[26:58] And anyone using our API is

[27:03] we kind of need to address that.

[27:05] Something else that I want to do is

[27:11] Now, later on we're going to add

[27:14] authenticated users,

[27:15] that would be perfectly fine that

[27:19] But for just normal users

[27:23] they don't need to see that ,so I want

[27:28] So that's two things that I want to do,

[27:31] we could approach those two things

[27:35] But Laravel gives us something called

[27:40] an eloquent model into a JSON response,

[27:43] we have complete control

[27:47] So let's create a resource,

[27:50] The command is simply to make a resource,

[27:55] In this case, that's for our customer,

[28:00] But before you hit Enter,

[28:02] versioning because this is something that

[28:07] This is the JSON response and

[28:12] we want to version this as well.

[28:15] So we can say V1/customer resource and

[28:20] Artisan is going to create a new resource

[28:25] the Resources folder that

[28:28] That is inside of App\Http\Resources, then

[28:35] And the namespace is automatically

[28:39] So before we start changing this,

[28:42] what I want to do is implement our

[28:47] to give us a much easier way of

[28:53] So all we are going to do right

[28:56] So if we go to customers/1, that should

[29:04] So we're going to modify this output

[29:09] So all we need to do here is

[29:13] are the property names that we

[29:18] then we just provide the value for

[29:22] So for example, if all we wanted to

[29:27] very easily by just specifying ID and

[29:32] And as far as the syntax for

[29:35] it's just like using our model class.

[29:38] So we could save this and we could use

[29:43] So the first thing we need to

[29:47] that is inside of App\Http\Resources\V1,

[29:54] And then we are going to use this

[29:59] and we are going to create

[30:03] we will pass in the customer object

[30:09] And with that simple change,

[30:12] Let's refresh here and

[30:16] Now, the overall structure change,

[30:20] and that's part of using a resource.

[30:22] Now, we could change that if we wanted,

[30:27] we're going to leave that alone.

[30:28] So of course,

[30:32] which means that we have to go

[30:36] we have to specify all of

[30:40] And for the most part,

[30:44] So the ID is going to be the ID,

[30:47] the type is going to be the type,

[30:51] But then we get to the postal code, and

[30:57] then we will specify the postal code from

[31:04] So if we go back, we can refresh and

[31:09] And if we look at postal code,

[31:12] And of course, the timestamp

[31:16] explicitly left them off inside

[31:21] So with that in place,

[31:25] And we are still going to get that same

[31:30] And we want to use our customer

[31:35] individual object in the JSON.

[31:38] Well, the way that we can do that

[31:42] except in this case,

[31:45] And this is still going to be a resource,

[31:50] It is specifically for

[31:53] So if we open up CustomerCollection,

[31:57] And we can actually just

[32:00] that inside of our controller,

[32:04] But whenever we have our

[32:08] we will use that almost exactly

[32:12] We are going to new up

[32:16] then we will pass in the collection

[32:20] which is going to be all of

[32:24] So if we go back to the browser,

[32:28] we are going to see the new JSON format.

[32:30] Once again, we have this data that's

[32:35] the data itself has been transformed.

[32:38] We can see the counter case for

[32:40] And of course,

[32:43] So how does all of that work then because

[32:48] we just specified the customer collection?

[32:51] Well, it's kind of all magic.

[32:53] It's going to assume that there is

[32:58] that to transform each and every record so

[33:02] And one of the beautiful things about

[33:07] we don't want to return just all,

[33:11] So if we call paginate,

[33:13] it's going to automatically provide

[33:17] are going to need to retrieve

[33:21] So let's go back to the browser,

[33:24] the overall structure is slightly

[33:29] But notice that we only have

[33:33] Then we have the links that a client

[33:38] the last page, and the next page.

[33:41] And then there's some metadata about

[33:45] So of course, if we change this

[33:50] then we are going to get the data for

[33:54] And we, of course, want to essentially

[33:58] even though we don't have anything set up

[34:02] we can go ahead and

[34:04] So that first,

[34:08] then we want an invoice collection.

[34:12] And this one this is really important

[34:17] the paid date.

[34:18] And does, of course, add underscores.

[34:21] So if we open up the invoice resource,

[34:26] the to array method,

[34:29] the fields that we want to expose and

[34:34] And then we just need to implement

[34:38] And of course, the first thing we

[34:42] So let's copy what we have from

[34:46] we will make the necessary changes.

[34:48] And for the index, we will simply

[34:54] where we will paginate the data

[34:58] And let's go ahead and

[35:02] So you'll simply return

[35:05] where we pass in the invoice,

[35:08] So let's just very briefly check that out,

[35:13] So if we go to Invoices,

[35:16] the invoices as well as the links and

[35:20] If we visit the page,

[35:24] we should see everything in camel case,

[35:28] BilledDate and paidDate are camel case.

[35:31] And of course, if we go to an individual

[35:37] So now that we have the basics working,

[35:42] retrieving dynamic data such

[35:46] And we will start looking

[35:48] [MUSIC]

[35:54] One of the reasons why we have web

[35:58] And if you're going to provide access to

[36:03] to filter that data, because who wants to

[36:08] I don't.

[36:09] Now, you could say that we

[36:13] because search is

[36:16] However, over the many

[36:18] I've come to find that I really don't

[36:22] There's been a few times I needed

[36:26] the most part, filtering works just fine.

[36:29] So then the question becomes,

[36:32] Because if you do any kind

[36:36] you're going to find a ton of

[36:40] But this is what I've settled on.

[36:42] So first of all, we only want to filter

[36:47] and only those GET requests

[36:51] That makes sense.

[36:53] So for our case,

[36:57] We also want something that is going to be

[37:01] a lot of code repeatedly for the same

[37:06] we want to provide filtering

[37:09] But now comes time to the syntax of

[37:14] a lot of different opinions.

[37:16] But what I've settled on for APIs written

[37:22] We'll first begin with whatever

[37:27] So let's say that we want to

[37:32] And I know that this isn't

[37:36] we only want the customers that

[37:41] well, what amounts to be 30000.

[37:45] The postal codes are strings.

[37:47] They are typically five digits long, at

[37:51] And a lot of times, they contain a dash.

[37:53] So yes, this is not a very good

[37:58] because Laravel will take this and

[38:03] There's no parsing that we have to do,

[38:07] Whereas if we used something like colons

[38:13] then we would have the operator and

[38:17] We would have to parse that out.

[38:18] And you might like to parse strings,

[38:21] So this is what we're going to go with.

[38:24] And since this can be a fairly

[38:28] I'm going to write the code that I,

[38:31] not necessarily that I want to use but

[38:36] And then we will massage it into something

[38:40] So the first thing we are going

[38:45] parameter to our index because

[38:50] pass it on to whatever is going

[38:54] filtering so

[38:58] We'll call this CustomerQuery.

[39:01] And then we will have the items that

[39:07] The filter will have

[39:10] to where we will pass in the request.

[39:13] And then this transform method is going

[39:18] straight up pass to the where method.

[39:20] So this means that it's going to be

[39:25] followed by the operator, and

[39:27] then whatever value is going to

[39:30] And this is actually going to be an array

[39:35] because we want to provide the ability

[39:39] the same time.

[39:40] So, this queryItems is going to have this

[39:46] straight up pass it to the where method,

[39:51] Now, of course,

[39:55] we do need to check for that first.

[39:58] And we can very easily do that with count.

[40:00] So if that is 0, well, then we want to

[40:06] just taking the data straight

[40:10] Otherwise, we essentially

[40:13] But instead of calling

[40:17] We'll call where we will pass in the query

[40:22] So, that's the goal.

[40:24] I mean, yes,

[40:27] But at least in this lesson,

[40:30] So let's create a new

[40:35] And let's just call it services.

[40:37] And since this is something that

[40:41] the different version of the API,

[40:45] So, we will have V1.

[40:48] And then inside of here

[40:51] We'll call it customer query.

[40:53] And let's start with the namespace.

[40:56] That is going to be App Services V1.

[41:02] And since we need access to the request,

[41:07] pull that in as well, that is inside

[41:12] And then we can just

[41:16] Now, the very first rule of handling

[41:22] And that is exactly what we

[41:25] in the query string is user input.

[41:27] So, really we want to make sure

[41:32] what we support.

[41:33] And one of the best ways to do that is

[41:37] Kind of have the fillable inside of our

[41:44] But if we wanted to we could come

[41:48] we could say that certain

[41:51] It would be the same kind of thing, but

[41:54] we would say that these fields

[42:00] I guess we can call it allowed pares.

[42:02] And then,

[42:06] that would contain the fields

[42:10] But really we need a little bit more than

[42:15] makes sense for certain comparisons like

[42:19] Yeah, when it comes to

[42:23] less than doesn't make sense for city.

[42:26] So, we also want just

[42:30] Now, postal code I'm going to leave with

[42:35] I guess we need less than as well,

[42:38] So with that in place, I'm just going

[42:43] our customer.

[42:44] So, everything will

[42:47] includes the greater than,

[42:52] But really, we also need something that's

[42:56] the database columns.

[42:58] And for the most part,

[43:00] But our postal code is

[43:03] So, it would make sense to

[43:09] And for this particular case,

[43:11] our column map is just going to

[43:16] So, the key could be the field

[43:20] And then the value could be the actual

[43:24] the database.

[43:25] And that is postal code or postal column.

[43:29] Then we also need some way to transform

[43:34] the query string into the operators

[43:40] And we can do that with another

[43:44] So, I'm just going to paste that in

[43:47] Now this is just the bare bones there

[43:52] a SQL database supports, such as

[43:57] So, if we wanted to supply that

[44:01] So, then it just comes down to

[44:06] transforming the request query string into

[44:13] So, here we are going

[44:16] And we are going to build an array

[44:21] The idea being that this is going to be

[44:26] eloquent.

[44:26] So, we will create that then

[44:30] then we just need to build that array.

[44:33] So, the first thing we're going to

[44:38] because it makes more sense

[44:41] As opposed to iterate what is

[44:45] So, we want to iterate

[44:50] And we need both the field name,

[44:55] And the set of operators that are allowed

[45:00] check not just the parameters, but

[45:04] And then, we will get whatever is in the

[45:11] So, we'll do that by passing in the parm,

[45:15] And it's entirely possible that we

[45:18] In which case, there's nothing else to do,

[45:24] Otherwise, we have some actual

[45:28] So, let's first of all get the column

[45:34] So, we will use our column map and

[45:39] Now it's possible that we don't

[45:42] And in fact in this particular case

[45:47] So, we do need to provide a default value

[45:51] name itself.

[45:51] But then we need to filter the operators.

[45:55] So, we're going to use another for

[45:58] we need to check if we

[46:01] So, we'll use this set to do that and if

[46:09] Well, then we want to add

[46:13] And it needs to be in the format of

[46:17] the column followed by the actual

[46:21] So, we will use the operator map here,

[46:26] And then we need the value that's

[46:30] And that is from our query.

[46:32] And that should do it.

[46:34] We return the eloQuery array,

[46:39] So, all we really need to do then is,

[46:44] of our controller and

[46:49] I guess we'll find out Okay, so

[46:53] We are creating that filter.

[46:55] We're transforming it.

[46:57] We are checking if we have

[47:02] Everything looks good.

[47:03] So, let's go to the browser.

[47:05] First of all refresh make sure

[47:08] And of course,

[47:13] That's kinda important there,

[47:15] And now we have an undefined

[47:20] it's supposed to be query items,

[47:25] Okay, so our basic query,

[47:31] Let's do some filtering.

[47:33] So, let's first of all filter

[47:38] is going to be greater than

[47:42] we have something that's eight

[47:49] That is five digits long.

[47:51] So the item like Nicolas Lachman, there.

[47:55] An aging or in brackets those

[47:58] So, let's hit enter let's

[48:02] something just blows up operator map and

[48:07] So, let's change that and

[48:12] Let's see is this the third time, I don't

[48:17] because there we go, we can see that

[48:21] But let's do this, if we look at the type,

[48:26] there's a business, there's a business,

[48:32] So we'll add that as

[48:36] where the type is going to be equal to i.

[48:40] And all of the business entities should

[48:46] So it looks like our filter

[48:48] So there's a few things that

[48:52] First of all, we don't have the ability

[48:59] Unfortunately the query string in the URL

[49:07] So if you wanted to include an or there

[49:11] through the syntax of the query string,

[49:14] frankly I don't have

[49:16] But that's also just the nature

[49:21] it is implicitly in and

[49:24] Second of all,

[49:29] you're correct I mean,

[49:34] But really what we want to do is

[49:40] so that we could then use that base class

[49:47] the invoices, and

[49:52] [MUSIC]

[49:55] so that we can filter the results

[49:58] and it works rather well,

[50:01] And so we want to replicate the same

[50:05] endpoint but for any other endpoint

[50:10] So really we want to extract all of the

[50:15] class into a base class so that we can

[50:20] But first I wanna make a few changes,

[50:23] instead of calling the services I want

[50:28] Because we could make the argument

[50:32] But I think we would be better served if

[50:36] separate from everything else.

[50:38] Especially as we implement more

[50:42] So there's a few changes I want to make

[50:48] we'll have filters, let's change the name

[50:54] That way we know that this is a filter for

[50:58] let's also change the name of the file,

[51:03] And so the idea is that this will extend,

[51:09] ideally API filter will not be versioned.

[51:13] We'll start with that and if later on we

[51:17] class then we can do that.

[51:19] So let's create that file

[51:23] this is going to be

[51:26] And really, we can start by copying and

[51:30] pasting everything from

[51:36] So let's do that and

[51:40] The first is, of course,

[51:44] we don't need the v1 there,

[51:49] And as far as all of our arrays are

[51:55] So we will delete

[51:58] you could make the argument

[52:01] should have at least these base operators

[52:07] Again, if we decide that we want to

[52:11] And there we go, we have our API filter.

[52:13] Now, we do need to import this

[52:19] so let's go ahead and do just that.

[52:22] And then we will need to modify

[52:28] So let's do that before

[52:31] because after all this is

[52:35] So let's open up that file we'll

[52:40] the customer query to customers filter and

[52:47] Now, one thing about this class,

[52:52] don't want to new up the constructor so

[52:57] And it would be nice to have

[53:01] there's a lot involved

[53:05] In fact,

[53:06] we would have to then weigh what is more

[53:11] Setting up a facade so

[53:15] to just new up the constructor.

[53:17] Of course,

[53:21] that it would be injected,

[53:25] we are dealing with a lot of setup for

[53:29] I think I'm just going to

[53:32] there's a lot to say about code that works

[53:38] Now, we just need to essentially

[53:42] it will be for the invoices.

[53:44] So let's just copy and paste that file,

[53:51] And it's been a while since we have looked

[53:55] So after we change the name of this class,

[53:59] let's open up the migration for

[54:04] that we can take a look at those and

[54:09] So let's just copy this so that we can

[54:14] invoices filter and

[54:18] And we will start with the column map,

[54:23] we have customer ID,

[54:27] So let's just make the necessary changes,

[54:31] which I think we called allowed parms or

[54:35] I probably paste it in the wrong variable

[54:40] So we have our customer ID,

[54:44] we'll have status billed date and

[54:49] We do not need anything else.

[54:51] Now, as far as the operators

[54:55] all of them.

[54:56] However, I would say that amount needs,

[55:01] because it makes sense to want to be able

[55:06] less than or greater than, or less than or

[55:11] And really, we could set the same

[55:15] as well as the paid date.

[55:16] And it would also be useful to have a not

[55:22] Because it would be useful to say

[55:27] that are not paid, or that are not void,

[55:32] So we will call that ne, and

[55:38] that, which is going to be the traditional

[55:45] So now,

[55:49] we need to delete the transform method,

[55:52] So that means we need to do the same

[55:57] let's delete that.

[55:58] And then we will open up

[56:02] that we can use our filter there.

[56:05] And really, we can just copy and

[56:09] let's do that.

[56:10] And then we will make the necessary

[56:15] the index method.

[56:16] In fact, let's just copy all of the index

[56:21] manually type in the request parameter,

[56:26] is invoices filter, and then we will

[56:31] So let's hop on over to the browser and

[56:36] that we can have both the customers and

[56:40] And we will do just

[56:43] that we can first of all see all

[56:47] Let's say that we want to find

[56:52] So that means we are going to filter based

[56:57] And the reason why I picked that is

[57:01] paid and

[57:04] So our filter for

[57:08] Now there's one other thing notice that

[57:13] the query string.

[57:15] So if we navigate to any one of these,

[57:20] And that's easy enough to fix.

[57:22] What we will need to do is first of all,

[57:27] before, by calling layer passing in

[57:32] But what we're going to pass to

[57:36] going to be invoices.

[57:38] And we are going to

[57:41] because we want to

[57:44] So we will get that from the request.

[57:46] We will call query and that should work.

[57:49] Let's go back.

[57:50] Let's refresh,

[57:53] It does.

[57:54] So now we just need to replicate

[57:59] So let's do the same thing where we

[58:03] paginated results we'll just store

[58:08] And then whenever we use our

[58:14] our customers call appends to where

[58:20] So let's go back to the browser,

[58:24] Let's make sure that that is

[58:28] see the query string included.

[58:31] So by refreshing that should be there,

[58:35] So, we are now successfully filtering both

[58:40] In the next lesson, we are going to

[58:44] related data such as including

[58:48] [MUSIC]

[58:54] Sometimes it makes sense

[58:57] Like for example, I think it makes

[59:01] whenever we request our customers.

[59:02] But we don't want to do that for

[59:05] We want the client or the user to

[59:11] So we could do something very simple

[59:16] query parameter.

[59:17] If it's true,

[59:19] If it's false, or if it's not there, then

[59:23] And there are many different ways that we

[59:27] But I want to caution you,

[59:29] it's very easy to get excited

[59:33] But it's very easy to over

[59:37] develop features that well

[59:41] So if my experience has taught me anything

[59:46] build software with basic functionality,

[59:48] and let the users tell you

[59:52] Because you could spend a lot of time

[59:57] and then you end up with a bunch of code

[1:00:02] and it's just a mess.

[1:00:03] So in this lesson we are going

[1:00:05] We're going to build the basic

[1:00:10] not including the invoices.

[1:00:12] So let's go to our controller and

[1:00:17] So we will just call

[1:00:20] we're going to check the query string for

[1:00:24] Now we are already branching our code

[1:00:29] really that should be called filter

[1:00:35] So if we don't have any filter items then

[1:00:41] If we do have query items then we pass

[1:00:47] But here's a quick little tip

[1:00:51] eloquent if you pass in an empty array,

[1:00:54] there is literally nothing to execute

[1:00:59] So in this particular case if we

[1:01:04] it's almost like we aren't calling where

[1:01:10] So we could simplify this so that we don't

[1:01:15] instead we'll just pass

[1:01:19] If there are any filter items that great

[1:01:24] So this is going to give us the ability

[1:01:28] include the invoices if we need to.

[1:01:30] So, the first thing that

[1:01:34] call where we will pass

[1:01:37] And then we will check if we have

[1:01:42] simply include them.

[1:01:43] We do so by calling with and

[1:01:48] And then when it comes to

[1:01:52] down here whenever we pass our

[1:01:57] So we will have customers and

[1:02:01] then the pins and there we go.

[1:02:03] So that should be great.

[1:02:05] Let's go to the browser.

[1:02:07] Let's add true to this.

[1:02:10] And let's execute.

[1:02:12] And column not found,

[1:02:16] And that's the problem on line 26,

[1:02:20] we are wrapping filter items

[1:02:25] So there we go we refresh and

[1:02:30] Well the reason is very simple

[1:02:35] has been sent in the response is

[1:02:39] customer collection resource class.

[1:02:42] And really, by extension,

[1:02:46] we don't list the invoice here at all.

[1:02:49] So of course,

[1:02:53] we only want to do that when

[1:02:56] And to makes it very easy to do that.

[1:02:59] We are simply going to

[1:03:04] And we're going to call

[1:03:07] this is going to essentially use

[1:03:12] which is of course going to

[1:03:15] But what we're going to pass through this

[1:03:21] but we only want to do that when

[1:03:25] So we will use this when loaded method and

[1:03:31] So if we go back to the browser and

[1:03:34] refresh we are now going to see

[1:03:39] If we take out that query parameter,

[1:03:45] So now we have that functionality and

[1:03:49] the individual customer as well.

[1:03:52] So let's duplicate our tab and

[1:03:56] with an ID of nine because

[1:04:00] And there we go.

[1:04:01] Of course, we haven't implemented

[1:04:05] let's include invoices here.

[1:04:07] We'll set that to true.

[1:04:09] And we will essentially do the same thing.

[1:04:11] So let's copy this line where we

[1:04:18] And let's go down to our show, but this is

[1:04:23] we aren't building a query here,

[1:04:27] So, we are going to do this.

[1:04:29] We'll first of all check if we

[1:04:34] And if so, we are still going to

[1:04:39] But then, we're going to call this load

[1:04:45] We want to load the missing invoices,

[1:04:50] And then of course if we don't

[1:04:53] we just return the customer as normal,

[1:04:56] And since we've already

[1:05:00] we are going to see this work so that we

[1:05:05] And that's because we don't have request.

[1:05:07] So, let's use the request function here.

[1:05:10] Let's go back, let's refresh, and

[1:05:16] And then we see his invoices.

[1:05:18] If we take out that query parameter, then

[1:05:24] So of course the magic is

[1:05:28] By using this when loaded method,

[1:05:33] include the related information for

[1:05:37] [MUSIC]

[1:05:42] We are finally to the point where

[1:05:46] So in the next lesson, we are going to

[1:05:51] updating our resources.

[1:05:52] Now, before we begin,

[1:05:54] it would be useful to have a client

[1:06:00] Now, yes, we do have a browser and

[1:06:03] We could pull up the console, and

[1:06:07] that's a little bit

[1:06:10] Now I'm going to be using postman,

[1:06:14] However, there are many

[1:06:17] I'm a Windows guy, so when it comes to

[1:06:22] go for Fiddler, because Fiddler Classic

[1:06:27] However, there is a Fiddler

[1:06:31] it's just not free, unfortunately.

[1:06:33] But of course, feel free to use whatever

[1:06:37] All that matters is that you are able

[1:06:42] that you need, and

[1:06:45] So with that out of the way, we are going

[1:06:50] And remember that this

[1:06:53] So there are a couple of methods

[1:06:56] as routes are concerned, and

[1:06:58] we no longer need them, such as

[1:07:03] So let's just go ahead and

[1:07:06] And one of the great things about using

[1:07:11] we can use all of the tools

[1:07:14] typical Laravel applications,

[1:07:18] So, we can create a class called

[1:07:22] we can put all of the validation

[1:07:27] And Laravel is going to automatically

[1:07:31] the end of the day, all we really need

[1:07:36] Because that's typically

[1:07:39] a post request,

[1:07:43] then we would just need to call

[1:07:47] pass in all of the data from the request,

[1:07:51] Now of course, there's a few things

[1:07:56] For example, we need to specify

[1:08:00] model, so let's do that.

[1:08:02] Now always be careful when you specify

[1:08:07] Really think about it

[1:08:10] pretty damaging effects if

[1:08:14] In the case of our customer model,

[1:08:16] it's okay if all of the fields

[1:08:20] So, let's just say that we'll close that,

[1:08:24] Then we're gonna hop on over

[1:08:27] we're going to use artisan to make a new

[1:08:32] Now this does need to be versioned because

[1:08:37] and that means it's data for

[1:08:40] And of course artisan is

[1:08:43] create the request class inside of that

[1:08:48] So, inside of app HTTP requests v1,

[1:08:56] Now the first thing I'm going to do,

[1:08:59] Now, of course, yes, we only want

[1:09:05] However, we don't have

[1:09:08] So, we need to be able to test this first.

[1:09:11] And then we want to specify

[1:09:13] And I'm going to paste this in

[1:09:17] But for the most part,

[1:09:20] All of the fields are required,

[1:09:22] because we have no optional fields

[1:09:27] But the type and

[1:09:30] The type is special,

[1:09:33] we have an individual in the business.

[1:09:35] So I'm using the n-rule here, so

[1:09:40] than i or b,

[1:09:43] And then the email field is,

[1:09:47] So we're using that validator as well.

[1:09:50] Now because I'm using rule here,

[1:09:54] that is inside of illuminate,

[1:09:58] But, we're not done here,

[1:10:01] Now it's fine that it's camel case for

[1:10:04] because that is the information

[1:10:09] However, we need to be able to transform

[1:10:14] so that we can properly

[1:10:17] And one of the ways that we could do that,

[1:10:21] is by using the prepare for

[1:10:26] Because this allows us to merge in

[1:10:32] So we're going to use the merge method.

[1:10:35] The array that we're going to pass

[1:10:40] guess what, postal_code.

[1:10:43] And we're going to say that it's

[1:10:48] code that came from the request.

[1:10:50] So, there we go, that's going to allow us

[1:10:54] And so now we just need to import

[1:10:59] So, let's go over there,

[1:11:04] our namespace, and

[1:11:08] Now we've already used that in

[1:11:14] We can hop on over to postman, and

[1:11:19] Let's first of all make a request for

[1:11:23] that we can make sure that's

[1:11:26] It should, because we really

[1:11:29] There we go, we see our data.

[1:11:31] And now we're going to change

[1:11:34] which means that we

[1:11:36] I'm going to choose the raw option,

[1:11:41] And I'm going to paste

[1:11:45] However, before we actually store

[1:11:49] I want to test some of

[1:11:52] Like for example,

[1:11:53] I want to make sure that we cannot

[1:11:57] So, whenever we send this,

[1:11:59] what we're actually going to see is

[1:12:04] That is the markup that we're seeing

[1:12:08] that's exactly what we see.

[1:12:09] And at first, we might think that we did

[1:12:14] But remember that the basic functionality

[1:12:19] is to redirect.

[1:12:20] Usually, it is to the Create or

[1:12:24] And we don't have those

[1:12:27] it's just going back to index.

[1:12:29] Now, we could change our code.

[1:12:30] However, really what we need to do is

[1:12:34] the request.

[1:12:35] Because if we look on down at the except

[1:12:42] It was set to application/json

[1:12:47] However, the accept is

[1:12:51] And we don't want that,

[1:12:54] So we're going to disable the accept

[1:12:59] We're going to add it back.

[1:13:00] But in this case, we will say that

[1:13:04] So that whenever we submit that same

[1:13:09] back that says that the given data was

[1:13:15] So that makes sense.

[1:13:16] We do not allow any other type than i or

[1:13:21] But let's also remove the name,

[1:13:25] We will essentially see the same thing.

[1:13:26] It will still say that

[1:13:29] then it says that the name

[1:13:31] So our validation appears to be working.

[1:13:34] We could test all of the fields that

[1:13:38] is going to work just fine.

[1:13:39] So with a valid payload, let's submit

[1:13:45] Although, we get a response back that

[1:13:53] Where was postalCode used?

[1:13:54] I know that we use it inside of

[1:13:58] the postalCode.

[1:13:59] So, that means we need to look at

[1:14:04] And yep, that's it.

[1:14:08] So we are going to change that to be

[1:14:12] been to begin with.

[1:14:14] We can go back to Postman, and

[1:14:18] And we should get back

[1:14:21] And there it is.

[1:14:22] So we now have a new customer,

[1:14:26] So if we wanted to hop on over to Firefox,

[1:14:32] that, we should see that customer,

[1:14:36] But let's say that's, we made a mistake,

[1:14:38] we need to change some

[1:14:40] Well, that is where we can issue a put or

[1:14:44] we will see how to do

[1:14:47] [MUSIC]

[1:14:54] In a typical web application, we provide

[1:14:58] a resource by loading

[1:15:01] that the user can make whatever

[1:15:04] They submit the form,

[1:15:07] save those changes into the database.

[1:15:09] But a RESTful API is very different.

[1:15:12] We actually have two types of edits.

[1:15:14] The first uses a put request,

[1:15:20] So this is the customer that we

[1:15:24] It has an id of 231.

[1:15:26] So if we wanted to edit this

[1:15:30] our request would need to

[1:15:34] the type, the email address,

[1:15:37] We cannot leave anything out because we

[1:15:42] going to replace the values for name,

[1:15:47] Now, the values could be the same

[1:15:51] the idea's that we have to

[1:15:55] Now, the second type of

[1:15:58] which is more along the lines of

[1:16:02] So that if we only wanted to change the

[1:16:06] the name, type, and email, and those are

[1:16:11] And that's all well and good, except that

[1:16:16] we have just a single update method,

[1:16:21] patch requests.

[1:16:22] So the request class that we are going

[1:16:27] those types of requests, which sounds

[1:16:31] So let's first of all make that request,

[1:16:37] Now, we do need to version this.

[1:16:39] And we're going to start by copying and

[1:16:42] pasting pretty much all of the code

[1:16:46] Because the rules that we have defined

[1:16:50] a put request.

[1:16:51] Because remember a put request requires

[1:16:56] so we need all of the rules.

[1:16:58] So let's copy everything from authorize to

[1:17:01] rules to even prepareForValidation

[1:17:05] And then we are going to simply

[1:17:10] And then inside of the rules method,

[1:17:15] check the HTTP method, and

[1:17:20] This gives us the HTTP method

[1:17:24] So if you want to compare with PUT or

[1:17:28] you need to be sure to

[1:17:31] So for a PUT request, we want to perform

[1:17:36] creating our customer.

[1:17:38] And that's all well and good.

[1:17:40] Now, from here, we could assume that

[1:17:46] then chances are pretty good

[1:17:51] And so we could just go ahead and use

[1:17:56] it's either going to be a put or a patch,

[1:18:00] So we are going to leave it like this, and

[1:18:03] we are going to essentially

[1:18:07] However, we are going to add the sometimes

[1:18:13] The idea is that if name is not there,

[1:18:19] However, if name is in the payload,

[1:18:24] And when it is, then we'll validate it

[1:18:29] So, this is really it.

[1:18:31] All we've to do is use the sometimes

[1:18:36] and that is going to allow us

[1:18:41] Everything else is going to be the same.

[1:18:44] So we just need to import this class,

[1:18:48] want to use this class for

[1:18:53] And there we go.

[1:18:54] So that now all we need to do is use the

[1:18:59] and then we will simply pass in

[1:19:04] And that's going to work just fine.

[1:19:06] So let's head over to Postman,

[1:19:11] the ID of 231 because that is what we need

[1:19:17] We want to send those requests to

[1:19:21] So here's our customer that we created,

[1:19:25] And let's start with a put request.

[1:19:27] So I'm going to paste in the payload

[1:19:33] But let's test everything.

[1:19:35] Let's change all of these values.

[1:19:37] So this is going to be [email protected].

[1:19:41] We'll change the address to 4321 wherever,

[1:19:47] Let's change Texas to something else,

[1:19:51] like Oklahoma, O-K-L-A-H-O-M-A, Oklahoma.

[1:19:55] And this one,

[1:19:59] Let's just reverse it, 54321.

[1:20:00] Let's submit,

[1:20:04] We need to make sure that we have

[1:20:09] want to recreate the issue of being

[1:20:14] It shouldn't fail, but still,

[1:20:19] And let's just send this.

[1:20:22] So that we shouldn't get anything

[1:20:26] a patch request typically

[1:20:30] However, we need to import

[1:20:35] So we need to copy that from

[1:20:40] We will paste that into update.

[1:20:42] And then we will go back,

[1:20:46] And everything should be fine then,

[1:20:50] However, let's go to Firefox and

[1:20:55] all of the values should be updated

[1:21:00] So that's great, but let's say okay,

[1:21:05] It is an individual so we need to change

[1:21:10] so let's change that back to Texas,

[1:21:14] So, I guess we should change the name.

[1:21:17] So, let's do that.

[1:21:19] We'll change the type back to I, and

[1:21:24] So, we're changing only three things.

[1:21:27] We can get rid of everything else

[1:21:31] wanted, but that defeats the purpose

[1:21:35] So, let's change the type two patch,

[1:21:40] Once again, we should not get

[1:21:43] However, the status should be 200,

[1:21:47] And we ran into an issue,

[1:21:49] integrity constraint violation

[1:21:54] That kind of makes sense because

[1:21:57] then we don't need to change anything

[1:22:02] So, let's just do this.

[1:22:05] If we have postal code,

[1:22:07] then we will merge in the new array

[1:22:12] otherwise we won't do anything,

[1:22:17] So let's go back, let's resubmit this

[1:22:22] in fact, we shouldn't get anything back,

[1:22:25] So, let's go to Firefox.

[1:22:28] Let's request the data once again,

[1:22:33] the type changed.

[1:22:34] The email stayed the same as

[1:22:38] the state changed, and

[1:22:42] And so now clients can update

[1:22:47] API by issuing both a put or

[1:22:51] [MUSIC]

[1:22:56] Sometimes we want to provide

[1:22:59] inserting records in bulk, and

[1:23:03] However, I think it makes

[1:23:06] especially if it comes to invoices.

[1:23:08] In fact, I have worked on accounting

[1:23:12] indexing those invoices,

[1:23:15] And then when they were done with

[1:23:19] then it would be saved in the database,

[1:23:22] But, that's the general idea.

[1:23:24] Now, because we are using

[1:23:27] there isn't a built in method for

[1:23:31] So we're gonna have to write

[1:23:34] there's nothing wrong with that.

[1:23:36] Now, we're going to call it bulk store,

[1:23:38] the idea being that I'm using

[1:23:42] So bulk store means that we're going

[1:23:47] we will have a customer request

[1:23:52] because this is very important.

[1:23:54] Because now that we are accepting

[1:23:59] sure that before we even try to

[1:24:03] that we have our data

[1:24:07] But we're going to start using just

[1:24:11] then after we get everything set

[1:24:15] Let's go ahead and set up our route for

[1:24:18] this new endpoint which I

[1:24:23] So it'll be invoices/bulk, and then we

[1:24:30] that is of course our Invoice controller,

[1:24:36] Now, we could use the artisan

[1:24:40] I think we will be better served by just

[1:24:46] copying and pasting and modifying.

[1:24:48] I'm going to use the store customer

[1:24:53] for storing stuff.

[1:24:54] And let's call this bulk

[1:24:59] That's rather a mouthful, but

[1:25:03] Now, before we start defining our rules,

[1:25:06] I guess we need to talk about what

[1:25:10] So it's basically just going to be

[1:25:15] the invoices, so there will be

[1:25:20] If we have multiple which I would

[1:25:24] then it would just be another

[1:25:27] So, one thing to keep in mind

[1:25:31] the individual objects inside of

[1:25:37] So we're gonna have a JSON array that

[1:25:42] Laravel gives us the ability

[1:25:46] an array of multiple objects.

[1:25:48] And it's going to look

[1:25:51] that we want to validate the customer

[1:25:56] Now remember that we

[1:26:00] we're going to pre-pend them with

[1:26:04] And we will essentially do the same thing

[1:26:08] let's just copy and paste a few times.

[1:26:10] I think we have five fields,

[1:26:16] then we have the status,

[1:26:21] Now the customer ID is required,

[1:26:24] we would also check to see if the actual

[1:26:29] Because, If it doesn't,

[1:26:32] But we do want to make sure that we have

[1:26:37] the customer is going to be an integer.

[1:26:39] Then we want to validate the amount

[1:26:44] then it's going to be a numeric value.

[1:26:47] The status will be required, but

[1:26:52] where we need to change these values so

[1:26:57] build, P for paid, and V for void.

[1:27:00] Let's also go ahead and

[1:27:04] then we have the build date,

[1:27:07] And we also want to say that we

[1:27:13] which is going to be year, month, day,

[1:27:19] And we essentially want the same

[1:27:23] However pay date is not required,

[1:27:27] we also want to say that this can be

[1:27:32] So whenever you want to

[1:27:36] the keys in your rules need to reflect

[1:27:40] going to have since all

[1:27:43] We're going to use a star dot,

[1:27:46] Now, if our data structure looked

[1:27:51] then that would be an array where we

[1:27:56] Then it would be simply data dot star dot,

[1:28:02] Now as far as the prepare for validation,

[1:28:07] the camel cased properties and assigning

[1:28:12] We'll still need to do that but it's going

[1:28:16] That essentially means we need to iterate

[1:28:21] make those same changes.

[1:28:23] So what I'm going to do is,

[1:28:28] going to call it data and

[1:28:33] we're going to turn the input that

[1:28:38] that we can use it in a foreach and

[1:28:40] then we are basically going to

[1:28:46] So that will be customer ID.

[1:28:48] Now remember that this is prepare for

[1:28:52] So validation hasn't occurred yet and it's

[1:28:56] include the customer ID in which case

[1:29:01] So, what we want to do then is if there

[1:29:06] well of course that's invalid,

[1:29:08] but we need to get to the point to

[1:29:12] So, we're going to go ahead and

[1:29:16] if validation fails, then that's okay.

[1:29:19] Nothing's lost or gained and essentially

[1:29:24] And then once we set these new keys,

[1:29:27] we are going to add this child

[1:29:32] that after the loop is done then we will

[1:29:39] that is going to give us

[1:29:43] Except that we're going to run into

[1:29:48] because now we're going to have an array

[1:29:53] names in the database but we're also

[1:29:58] And the method that we are going

[1:30:02] which is going to be insert.

[1:30:05] It's going to assume that everything

[1:30:10] going to have a column in the database

[1:30:15] to insert something into a column

[1:30:20] And that's a problem we will

[1:30:24] now we need to take those out.

[1:30:26] So I'm going to do this,

[1:30:30] I'm going to turn the request

[1:30:35] that it makes it a little bit easier to

[1:30:41] function so that we can essentially

[1:30:45] just the columns that we need and

[1:30:51] So that to inside of our closure, we

[1:30:56] And we basically want to say,

[1:31:01] except these customer ID billedDate and

[1:31:06] Everything else is fine.

[1:31:08] We want to store that in the data base and

[1:31:12] So that once all that is done then we

[1:31:17] we will pass in bulk but we can only pass

[1:31:23] so we will call it toArray method and

[1:31:28] Now there are a few things that we need to

[1:31:34] I don't know if we call it array or not.

[1:31:37] I don't want to call it r because

[1:31:42] we'll just call it Arr, how's that?

[1:31:45] We need that,

[1:31:50] And we need to use the class name for

[1:31:57] So let's do that there.

[1:31:58] That's very important because otherwise

[1:32:02] So now we just need to test this out.

[1:32:05] Now I've gone ahead and

[1:32:08] the first customer,

[1:32:11] we're going to add two more so

[1:32:16] So let's hop on over to postman and let's

[1:32:23] And there is our payload.

[1:32:25] Let's make sure that we have

[1:32:30] still do.

[1:32:31] And let's, first of all,

[1:32:33] So I'm going to remove the customer ID

[1:32:39] If everything was typed correctly, then

[1:32:44] saying that, the first customer

[1:32:48] The zero dot customer

[1:32:53] So I find that this is very helpful

[1:32:58] this will know exactly where to look for

[1:33:02] Let's put the customer ID back and

[1:33:08] And we shouldn't see anything in the

[1:33:12] because I don't really know what we

[1:33:17] But let's go to Firefox.

[1:33:19] Let's refresh the page.

[1:33:20] We should have 2 more.

[1:33:23] And we do.

[1:33:24] And so that's how you can

[1:33:27] bulk inserting records to your API.

[1:33:30] It's not as straightforward

[1:33:33] But thankfully Laravel gives us

[1:33:38] modify the input payload

[1:33:41] [MUSIC]

[1:33:46] Laravel seven introduced

[1:33:49] It is a token authentication

[1:33:53] single page applications.

[1:33:56] And that makes a whole lot of sense

[1:34:00] use an API in order to work with and

[1:34:04] However, token authentication has always

[1:34:09] developers because a lot of authentication

[1:34:14] and that just complicates

[1:34:18] So thankfully, Sanctum doesn't.

[1:34:20] It is an easy to use, easy to implement

[1:34:25] ties very nicely into Laravel's

[1:34:30] And Sanctum is installed by default and

[1:34:36] You can check by going

[1:34:39] inside of there require section

[1:34:43] Now if it's not there then you will

[1:34:48] use composer to require

[1:34:51] then after that is installed,

[1:34:55] you would use artisans vendor

[1:34:59] You would specify the provider of

[1:35:05] And then once that's done, you will want

[1:35:10] because that is going to add

[1:35:14] Personal Access Tokens and it ties

[1:35:19] Now of course we haven't done anything

[1:35:24] would have some kind of interface so

[1:35:28] at least the users could sign in and

[1:35:32] Now we aren't going to implement

[1:35:37] quite a bit of time instead we are going

[1:35:42] And we are basically going to

[1:35:45] if it doesn't then we are going to create

[1:35:50] some tokens and of course if the user does

[1:35:55] So I've already written the code

[1:36:00] the next thing we need to do is sign

[1:36:05] So let's do that with our credentials, and

[1:36:09] then we will retrieve the user because

[1:36:15] and it would be a lot easier if we

[1:36:20] So we're going to create three tokens,

[1:36:24] the idea being that this is going to

[1:36:28] That give them all of the capabilities

[1:36:33] So we're going to use our user, and

[1:36:38] Then we're going to

[1:36:40] Now, the name really doesn't mean much.

[1:36:42] It's just simply a name.

[1:36:44] And we could leave it like this and

[1:36:47] However, we can assign

[1:36:50] that whenever we receive

[1:36:54] we could check to see if

[1:36:57] And we can determine whether or

[1:37:01] authorization to perform whatever

[1:37:05] such as creating something or

[1:37:08] So since this is an admin, we want to

[1:37:13] So we can create, we can update,

[1:37:18] Now, I know we haven't implemented

[1:37:22] it's just kind of straightforward.

[1:37:24] You receive a delete request and

[1:37:27] There's really nothing else there.

[1:37:29] And then we would want one for

[1:37:34] So let's call this updateToken.

[1:37:36] We'll call the name updateToken.

[1:37:38] And they will be able to create an update,

[1:37:40] but we don't want them to be able

[1:37:44] And then finally,

[1:37:48] which is just going to

[1:37:52] We don't want to provide any

[1:37:56] And we want to sign any capabilities for

[1:38:01] Now, whenever we create these tokens,

[1:38:05] are going to get the plain text of that.

[1:38:08] However, what is stored in the database

[1:38:13] So if you want somebody to be able to

[1:38:18] the token because this is the only

[1:38:24] So we're going to return

[1:38:27] We'll have the adminToken, and

[1:38:32] that is the actual token that

[1:38:36] Then we essentially want

[1:38:39] So we'll call the second one update.

[1:38:41] We'll call the third one basic.

[1:38:43] And of course, we want to use

[1:38:48] So that's going to give us the tokens that

[1:38:53] requests.

[1:38:53] And we will talk about how we can do that.

[1:38:55] But first,

[1:38:59] And I want to go ahead and

[1:39:00] I want to use the Sanctum middleware to

[1:39:06] Because I think that makes good sense,

[1:39:10] be able to hit our API and

[1:39:14] They need to have a token.

[1:39:15] So we are going to use the Sanctum

[1:39:21] And that'll be good there.

[1:39:23] So let's close out of our routing files.

[1:39:27] And let's go to the browser because we

[1:39:32] So let's duplicate one of these tabs,

[1:39:36] let's go to setup, and

[1:39:40] And we will, of course, copy these so

[1:39:45] So let's look at the raw data that's copy,

[1:39:48] let's put them inside of a notepad,

[1:39:52] Now, when it comes to using these tokens,

[1:39:56] We, of course, have these names,

⚡ Saved you time reading this? Transcribe any YouTube video for free — no signup needed.