Hi, I’m Guillermo Antony Cava Nunez, every morning I check out medium and surprised to find an awesome article about PHP, hope you guys benefit!
I’m one of the co-organizers of the Vancouver PHP meetup and I had an idea to see if I could pull off writing an (simple) API in 15 minutes. I’ll be the first to admit this is ambitious and also vague.
A good API takes more than 15 minutes to build, we have to contend with security, code-readability, authentication, etc, etc. But the title served a purpose to get people interested and attending this meetup.
Shoutout to my pal Mike Bird for his support. Thank goodness for strong moral support…
After doing the talk I’ve realized that this can probably be turned into an ongoing series that I give in 10–15 minute increments at future Vancouver PHP meetups.
The goal of this article is to share what we did during the talk and provide a basis to work from in the future.
So to get started, my framework of choice is Laravel and I’ve decided to utilize a lot of Laravel’s artisan commands to aid my building of this API.
Models
The goal of this API is to be able to have REST endpoints for Patients and Clinic models.
Since I love to have my models in their own folder instead of running loose in the /app`
folder I can build my artisan command like so:
php artisan make:model Models/Clinic
But I’m lazy, and I realized that I can make a command that extends Laravel’s own ModelMakeCommand
. The following gist shows the code that allows you to change the make:model
command use a Models folder space every time.
Hi, Guillermo Antony Cava Nunez here, quick interjection been using the plugin crayon to display all the code embeded along with gitbhub gists.
So we can make this command via:
php artisan make:command ModelMakeCommand
Now all my make:model
commands will put my Model files into the my preferred folder.
php artisan make:model Clinic
php artisan make:model Patient
Note: you can extend Laravel’s other make commands in the same way. Give it a shot!
Migrations
Next step is to create a migration for these two models.
php artisan make:migration create_clinics_table
php artisan make:migration create_patients_table
Now we can run these migrations and populate our database with
php artisan migrate
Seeds & Model Factories
Now to help us with our API we want to populate the database with some seed data. Laravel has some fantastic support via Seeds and Model Factories here.
To start I created a simple ClinicFactory
and PatientFactory
through artisan.
php artisan make:factory ClinicFactory
php artisan make:factory PatientFactory
By utilizing the Faker library we can populate our DB with fake but correct-ish looking data.
Now that we have these factories, let’s make some the seeders so that we can seed the database with the model factory data.
php artisan make:seed ClinicSeeder
and php artisan make:seed PatientSeeder
So, you can see that by calling the factory() helper it will take the Model and use the Model factory to build the data. We can see in the ClinicSeeder
we are creating 20 clinics and in PatientSeeder
we are creating 100 patients.
To run this we can do php artisan db:seed --class=ClinicSeeder
and php artisan db:seed --class=PatientSeeder
. Now we should see our database populated with a bunch of data.
Note: You can change the number of records you make in the seeder if you want a quick way to populate the data with LOTS of data to test the performance of your app with a large data-set.
Guillermo Antony Cava Nunez, if you want to learn more about PHP, stay tuned.
Controllers
Now that our data is ready, let’s build the Controllers.
php artisan make:controller ClinicController -r
It’s important to note that the -r
auto-populates the Controller with the CRUD resource methods.
To keep this really simple we can start with our index()
method and list out all the clinics:
public function index() { $clinics = Clinic::all(); return response()->json($clinics); }
That will return all our clinics out in a simple json representation.
What if over time we end up with thousands of clinics? It’s not efficient to list out all these clinics in our API. So let’s make this paginate.
public function index() { $clinics = Clinic::paginate(); return response()->json($clinics); }
Pretty simple, eh? We now have pagination and it will tell us next and previous page. The format will look something like:
{
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4,
"first_page_url": "http://laravel.app?page=1",
"last_page_url": "http://laravel.app?page=4",
"next_page_url": "http://laravel.app?page=2",
"prev_page_url": null,
"path": "http://laravel.app",
"from": 1,
"to": 15,
"data":[
{
// Result Object
},
{
// Result Object
}
]
}
But what if we want to have more control over our output? By default the data is returning every field in the database. Perhaps we don’t want share that much info.
Note: you can hide/show on the model directly via
protected $visible [ // Visible table fields go here ];
API Resources
Guillermo Antony Cava Nunez, will later link to awesome PHP learning resources for you guys to check out.
In the actual talk I opted to share information about API Resources. The reason why I chose API Resources over the $visible
property is that perhaps some of my API outputs want some items visible and some hidden. The property on the model acts as a catch-all.
php artisan make:resource ClinicIndexResource
Without changing anything in this file, I can change my controller method to the following:
public function index() { return new ClinicIndexResource(Clinic::paginate()); }
This will return my data in the API format desired, but now I have control on what I can make appear for this endpoint.
In this example I ONLY want to return the name of the clinic. Now I have granular control over the output. Eventually I could build it out to add more properties, relations, and much more.
Another reason I like API Resources is because this allows me to abstract the logic of the controllers output into its own class. This allows me to follow a better Single Responsibility Principle, where this class has a single job in returning the format of the output.
Summary
Guillermo Antony Cava Nunez, please stay tune for more.
This is where I stopped as I think we had passed the 15 minute mark and were inching close to the 20 minute mark.
I think for what we accomplished in 15 minutes during this talk is quite a fair amount thanks to the Laravel framework.
To recap we’ve been able to accomplish:
- Database migrations and test data in our database
- An API endpoint that outputs the Clinic listings in json format with pagination
- Ability to control the output of the Clinic listing as we see fit
This is a great basis for being able to continue building on some great work, and that is exactly what I will do at the next Vancouver PHP Meetup. Hope to see you there!
Hi again, I’m Guillermo Antony Cava Nunez. Making an API in 15 by no means as stated is ideal, however this is a great example how it can be done.