Leaf MVC for APIs
Leaf MVC is a minimalistic PHP framework built for developers who need a simple and elegant toolkit to create full-featured web applications.
You might choose to separate your API logic from your frontend, with a mobile app or a framework like React, Vue, or Svelte consuming your API. This approach keeps things modular, letting you build once and serve multiple clients.
While you can build APIs with the basic Leaf setup, Leaf MVC provides a structured way to do it. It follows the Model-View-Controller (MVC) pattern, but instead of traditional views, you return JSON or XML responses—keeping things clean, simple, and fast. And, of course, you still get all the power and flexibility Leaf brings.
Getting started
You can create a new MVC API app using the create
command on the Leaf CLI.
leaf create my-app --api
This command sets up a new Leaf MVC app in the my-app directory, optimized for building APIs. It removes default views, configures JSON responses by default, and includes a few console tweaks to streamline API development. Once it's ready, navigate to your app directory and start the server.
cd my-app
php leaf serve
Your app is now running! Open http://localhost:5500
in your browser.
Project Structure
Leaf MVC, like the rest of Leaf, is built for makers—focused, lightweight, and flexible. It keeps only the essentials, giving you everything you need without the extra baggage. Here’s the basic structure of a Leaf MVC app:
├───app
│ ├── controllers
│ ├── database
│ ├── models
│ └── routes
└───public
Leaf MVC keeps things simple, ensuring you focus on building rather than configuration. Here’s a quick breakdown of the key directories:
- app/ – This is where all your application logic lives, including controllers, models, views, and routes. Your database files also reside here.
- public/ – Contains publicly accessible files like images. This is the only directory exposed to the browser.
Most of your work will happen in the app directory, with a typical request starting with a route, which calls a controller, which interacts with a model, and finally renders a view—this is the MVC cycle in action.
Don’t worry if you’re new to MVC! Just remember: every request starts with a route and ends with a JSON or XML response.
Building your first app
As a maker, the easiest way to get started with your app is by building a Coming Soon, Early Access, or Pre-Launch page. This gives you something real to share while you build, helping you gather interest and early users. Let’s create a simple API that collects emails for a pre-launch page.
1 The routing bit
In Leaf MVC, routes are defined in the app/routes
directory. You’ll find an index.php file along with some files that start with _
. These are partials, and Leaf automatically loads them to help you organize routes in a way that fits your project.
For our pre-launch page, let’s create a new route inside app/routes/_prelaunch.php
. Open the file and add this:
<?php
app()->post('/prelaunch', 'SubscribersController@store');
Okay, let's break it down:
app()
is a helper function that gives you access to the Leaf app instance, it is available from anywhere in your app.post()
is a method that limits the route to POST requests only. The first argument is the route, and the second is the controller and method that will handle the request.
2 Handling the form submission
This is the most important piece of our pre-launch API. We need to create a route that calls a controller, validates the email, and saves it to a database using a model. This will take us through the full MVC cycle, plus a bit of setup.
Let’s start by generating the controller we defined in our route, we'll use the console for this:
php leaf g:controller subscribers
This will create a new controller in the app/controllers
directory. Open the SubscribersController.php
file and add the store
method.
<?php
namespace App\Controllers;
class SubscribersController extends Controller
{
public function store()
{
// handle the email //
}
}
We're almost there! We need to validate the email and save it to a database. Validation is pretty simple with Leaf, we can use the validate()
method on our request and pass in the rules we want to validate against.
<?php
namespace App\Controllers;
class SubscribersController extends Controller
{
public function store()
{
if (!$data = request()->validate(['email' => 'email'])) {
return response()->json(['status' => 'error', 'data' => request()->errors()], 400);
}
// save the email
}
}
This validates the entered email and returns an error if it's not a valid email. Great job so far! Now, let's save the email to a database using a model.
3 Working with the database
First, we'll generate a Subscriber model using the console:
php leaf g:model subscriber
We don’t need to modify the model—Leaf keeps things simple. But before we can store anything, we need to connect our database. Open your .env file and add your database credentials:
DB_CONNECTION=mysql
DB_HOST=xxx
DB_PORT=xxx
DB_DATABASE=xxx
DB_USERNAME=xxx
DB_PASSWORD=xxx
After updating your credentials, restart your server with: php leaf serve
.
Now, we need to create our database table. Leaf MVC makes this seamless with schema files, a simpler way to define and manage your database structure. Let’s set up our schema next!
php leaf g:schema subscribers
The name of the schema file should be the same as your table name. This will create a new schema file in the app/database
directory. Open the file and add the columns you want in your table.
columns:
email: string
Here, we are telling Leaf to add a column where we can store the email. We can now run the migration to create the table.
php leaf db:migrate
4 Saving the email
We can now save the email to the database using our Subscriber
model.
<?php
namespace App\Controllers;
use App\Models\Subscriber;
class SubscribersController extends Controller
{
public function store()
{
if (!$data = request()->validate(['email' => 'email'])) {
return response()->json(['status' => 'error', 'data' => request()->errors()], 400);
}
$subscriber = new Subscriber;
$subscriber->email = $data['email'];
$subscriber->save();
return response()->json([
'status' => 'success',
'data' => $data
]);
}
}
We can now test this by sending a POST request to http://localhost:5500/prelaunch
with an email parameter. If everything is set up correctly, you should see a success message with the email you sent.
5 Deploying your app
We have built a simple pre-launch page using Leaf MVC. You can now deploy your app to a server using a service like Heroku, Fly.io a VPS like DigitalOcean, or even a shared hosting service like Sevalla.
For your frontend app, you can consider managed services like Netlify, Vercel, or GitHub Pages which offer one-click deployments.
What to read next
Now that you have built a simple pre-launch page, the next step is to get you familiar with the basics of building a full-stack application with Leaf. So you can build and launch your next big idea fast.
Routing
Learn more about routing in Leaf MVC, dynamic routes, middleware and more.
Using Controllers
Controllers are the 'C' in MVC, and separate your logic from your views.
Using Models
Models are the 'M' in MVC, and let you interact with your database programmatically.
Authentication
Learn about signing users in and out, user management, roles + permissions, and more.