Pre-requisites
First, create your application
laravel new sanctum-example
laravel new sanctum-example
We'll assume 3 things:
We're going to create another table called Second which contains options. These options can be set when we create a YourModel record, but we'll also need to retro-set the existing YourModel records with the new Second model values
We'll begin with a new model. The -m creates a migration file for the model.
php artisan make:model Second -m
Now we'll open the newly created migration file.
Inside the function up()
, add the new fields e.g.
$table->string('name')->unique();
This time we're going to specify the record values to be migrated. At the end of the function up()
, add:
DB::table('second')->insert([
[
'name' => 'Type 1'
'created_at' => now(),
'updated_at' => now(),
],
[
'name' => 'Type 2'
'created_at' => now(),
'updated_at' => now(),
],
[
'name' => 'Type 3'
'created_at' => now(),
'updated_at' => now(),
],
]);
Now we need to make another migration to add SecondModel values to the original YourModel records:
php artisan make:migration add_secondmodel_id_to_yourmodel
A foreign key will be required to link a record in YourModel, to a record on the SecondModel. In this newly created migration we can populate the
Schema::table within the function up()
with:
$table->foreignId('second_id')->nullable()->after('id')->constrained();
Now we'll append the function drop()
, by populating the Schema::table:
$table->dropForeign('second_id');
$table->dropColumn('second_id');
Now in the YourModel file, we need to add 'second_id'
to the $fillable array
.
The $fillable array is used to prevent unauthorised data manipulation by limiting which attributes can be set on a model.
Now in the YourModel file, we need to add a function second()
, which returns
$this->belongsTo(Second::class);
to make the link.
Now we need to open the YourFactory.php
and within the function definition()
return array, add:
'second_id' => and(0, 1) === 0 ? NULL : Second::pluck('id')->random(),
This will populate the foreign keys of existing records using YourModel with random values from the SecondModel.
We should also update the StoreYourRequest file, by adding to the return array of function rules()
'second_id' => 'nullable|exists:second,id'
then creating:
public function attributes()
{
return [
'second_id' => 'second'
];
}
We'll now need to create a resource, so that we only communicate the fields we need through the API:
php artisan make:resource SecondResource
Then reset the return values of the function toArray()
return [
'id' => $this->id,
'name' => $this->name,
];
Now on the YourResource, add append Second to the return values of the function toArray()
, thus
'second' => SecondResource::make($this->whenLoaded('second'))
Finally, it's now time to run the migrations:
php artisan migrate:fresh --seed
We'll assume 3 things:
Now open the YourController.php.
Develop the function destroy()
like this:
public function destroy(YourModel $yourmodel)
{
$yourmodel->delete();
return response()->noContent();
}
To test this in Postman, you'll need to send a DELETE request with the URL of http://localhost/api/yourcontroller/1
In the Headers tab add the key Accept and the value of application/json
In the body select none instead of raw.
Try using an empty object to see if the API returns the validation message.
That should work.
We'll assume 3 things:
Http/Requests/UpdateYourRequest.php
.YourController.php
and remove the edit method.function update()
thus:public function update(UpdateYourRequest $request, YourModel $yourmodel)
http://localhost/api/yourcontroller/1
application/json
{
We'll assume 3 things:
This exercise will include adding validation of the incoming data.
When we created the model, we selected Form Requests, which created Http/Requests/StoreYourModelRequest.php
and Http/Requests/UpdateYourModelRequest.php
.
A Form Request in Laravel is a class that encapsulates the validation logic for a form submission. It allows you to separate the validation logic from your controller and makes it easier to reuse the same validation rules across multiple controllers.
We will edit StoreYourModelRequest.
If we're not using authorization the function authorize()
should return true
.
Now we will validation rules to the name field, thus:
public function rules()
{
return [
'name' => 'required|string|max:255'
];
}
Now in the YourController, we don't need the create method, so delete it. We just need to have a function store() which looks like this:
public function store()
{
$yourmodel = YourModel::create($request->validated())
return YourResource::make($yourmodel);
}
Now in the your model add the attribute
protected $fillable = ['name'];
$fillable is used to prevent unauthorised data manipulation by limiting which attributes can be set on a model.
To test this in Postman, you'll need to send a POST request with the URL of http://localhost/api/yourcontrollername
In the Headers tab add the key Accept and the value of application/json
In the body select raw and choose the data format JSON.
Try using an empty object to see if the API returns the validation message
Now try an object like this:
{
"name": "My name"
}
That should work.
We'll assume 3 things:
Using the Eloquent API Resource to streamline data transferred by a Laravel 11 API Model
The Eloquent API Resource acts as a transformation layer between your eloquent models and the JSON responses. The object of this exercise is to specify only the fields we want to return to the requester, and contain the data within a data object.
To create an API resource run:
php artisan make:resource YourResource
Now the file is in the Resources directory.
Go to the Http/Resources/YourResource.php
file
We will edit the function toArray()
This time we will return an associative array of fields e.g.
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
// Note no description
];
}
Our next step is to change the function index()
in YourController.php, this time returning
YourResource::collection(YourModel::all());
database/factories
.function definition()
, add the field names and the corresponding values to each field. Here's an example:public function definition(): array
public function run(): void
php artisan migrate --seed
function index()
, had some test output of "Hello world" which we tested in Postman. Now we're going to add a listing of the records from our model within our controller and return that as JSON instead. Look for your controller in Http/Controllers/
then edit thus:public function index()
We'll assume that the model was created using the approach in this blog post.
When the model was created in the pre-requisite, a migration file was also created for our model in the directory database/migrations
.
It is in this file that we set the field types which will be populated as records are used within CRUD operations and listings. Below are examples of how these should be set in order to facilitate this:
public function up(): void
{
Schema::create('yourmodel', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('yourmodel');
}
It would be possible to run the migrations as is though:
php artisan migrate
but we may be best served, by seeding these migrations as we run them in order to have some test data.
routes/api.php
for this model.php artisan install:api
Route::apiResource('/yourmodelname', YourController::class);
php artisan route:list --path=api
return response()->json(['message' => 'Hello World!']);
php artisan serve
http://localhost:8000/api/yourcontrollername
We should now see some JSON showing the message "Hello world".
php artisan make:controller
php artisan make:model
I'll assume that you have Laravel set up to use laravel commands.
Make sure you have SQLite installed.
First, create your application:
laravel new basic-api
Apply the API
php artisan install:api
Delete the resources
directory
Delete the file routes/web.php
Delete the line web: __DIR__.'/../routes/web.php',
from bootstrap/app.php
This post is specific to Laravel 11, which has a sightly different way of setting up it's API to previous versions.
I'll assume that you have Laravel set up to use laravel commands.
Make sure you have SQLite installed.
Run:
laravel new basic-test
To question 'Would you like to install a starter kit?', select 'No starter kit'.
To question 'Which testing framework do you prefer?', select 'Pest'.
To question 'Would you like to initialize a Git repository?', select 'yes'.
To question 'Which database will your application use?', select 'SQLite'.
To question 'Would you like to run the default database migrations?', select 'yes'.
To question 'Would you like to create it?', select 'yes'.
Run:
cd basic-test
Run:
php artisan install:api
Within routes/api.php, add the following lines below the 'use' statements:
Route::get('/', function () {
return response()->json(['message' => 'Hello World']);
});
Run:
php artisan serve
Open a web browser, and add http://127.0.0.1:8000/api/
to the address bar.
You should see some JSON showing the message 'Hello world'.