Spark is a PHP micro-framework that follows the Action-Domain-Responder (ADR) system. It is PSR-1, PSR-2, PSR-4 and PSR-7 compliant. Spark allows a developer to fairly quickly create a RESTful API as you’ll see in this article.

In this article, we’ll be using Composer to install Spark and other dependencies.

Initial Setup

Using Composer, pull down the Spark project using the following command. This will pull the latest version of the project from Github and place it into a new folder called ‘spark-project’.

[code linenumbers=”off”]
composer create-project -s dev sparkphp/porject spark-project
[/code]

We’ll be connecting this application to a database backend and so you can follow along, you can use the following MySQL statement to create an exact replica of my schema.

[code]
CREATE DATABASE `spark_project`;

CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`comment` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) NOT NULL,
`first_name` varchar(45) DEFAULT NULL,
`last_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username_UNIQUE` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
[/code]

To make accessing this database easier, we’re going to use the FluentPDO library. To install FluentPDO, go into the ‘spark-project’ directory and open the composer.json file and add the following line inside the “require” block:

[code]
“lichtner/fluentpdo”: “dev-master”
[/code]

Using the ‘composer update’ command will download FluentPDO and put it in your “vendors” folder.

Let’s Begin

For ease of access, this article will be using the built-in PHP web server. To start that, use the following commands:

[code]
cd spark-project
php -S localhost:8000 -t web/
[/code]

You should now be able to open a browser and goto http://localhost:8000/hello and receive some JSON output similar to the text below:

[code]
{“hello”:”world”}
[/code]

Dependency Injection

Now that we’ve got the project running, let’s add some additional features to show how quickly you can get an application up and running with Spark.

Go ahead and open “web/index.php”. At the top of the file, you should see a line like:

[code]
$app = Spark\Application::boot();
[/code]

This method bootstraps Spark and optionally takes a parameter that handles the dependency injection. Since we’re using FluentPDO, we need to manually create this injector,
add FluentPDO to it and pass it into the boot() method so that Spark knows about it. We do that by replacing the previous line of code with following, making sure to replace any login specific information:

[code]
$fluentpdo = new FluentPDO(new PDO(‘mysql:dbname=spark_project;host=‘, ‘‘, ‘‘));

$injector = new \Auryn\Injector;
$injector->share($fluentpdo);

$app = Spark\Application::boot($injector);
[/code]

By creating your dependencies and passing them into Spark during bootstrap, this allows the application to recursively inject them using Reflection. To utilize an injected class in a Controller, you simply create a __construct method inside the specific Controller and type-hint an argument using the class name, like so:

[code]
public function __construct(\FluentPDO $fpdo) {
$this->fpdo = $fpdo;
}
[/code]

Adding Users

Now let’s go ahead and implement a new Controller, we’ll start by adding an additional ‘GET’ route to the application. In the “web/index.php” file, you should see some lines that look like this:

[code]
$app->addRoutes(function(Spark\Router $r) {
$r->get(‘/hello[/{name}]’, ‘Spark\Project\Domain\Hello’);
});
[/code]

Since we want to add another route, just add a line right below the ‘$r-get()’ line. The format for the routes is $r->METHOD(PATH, ACTION). Go ahead and add the following line below the current route:

[code]
$r->get(‘/user/{name}’, ‘Spark\Project\Domain\GetUser’);
[/code]

In the above example, you see that ‘name’ is wrapped in curly braces. This tells Spark to assign that part of the URL to an input variable named ‘name’. If the whole thing would have been wrapped in square brackets (‘/user[/{name}]’), it would be considered an optional argument.

Now that we have the route specified, we need to create the backing class, “GetUser”. Create a new file under src/Domain named ‘GetUser.php’ with the following code inside:

[code]
fpdo = $fluentpdo;
}

public function __invoke(array $input)
{
if (empty($input[‘name’])) {
return (new Payload)
->withStatus(Payload::ERROR)
->withOutput([
‘error’ => ‘Missing name argument’,
]);
}

$name = $input[‘name’];
$users = $this->fpdo->from(‘users’)
->where(‘username’, $name);

$output = [];
foreach ($users as $user) {
$output[] = $user;
}
return (new Payload)
->withStatus(Payload::OK)
->withOutput($output);
}
}
[/code]

Looking through the code, you can see we’re wanting to use FluentPDO inside this class, so we’ve added that to our constructor method. The __invoke method is passed an array named $input, this array is built by Spark and contains the input variables from various different places: POST, GET, uploaded files, cookies, etc. Inside the __invoke method, you can see that we’re going to verify that a ‘name’ was sent along with the request, if not, we’ll throw an error back. If everything checks out, FluentPDO is used to pull the user from the database based on the name that is passed in, and the full details of said user will be returned in a JSON string.

Using FluentPDO makes querying the database extremely simple. In our case, we simply specify the table and single where clause. FluentPDO can perform much more complicated queries, like JOINs, very easily and can really cut down on time spent writing queries.

If you navigate to http://localhost:8000/user/test, you’ll end up with an empty JSON object. This is obviously because we don’t currently have any users created in the database. To do that, we’re going to create another action and route to handle POST requests to create users. Go ahead and create a new file under ‘src/Domain’ named ‘DoUser.php’ with the following code:

[code]
fpdo = $fluentpdo;
}

public function __invoke(array $input)
{
$user = [
‘username’ => $input[‘name’],
‘first_name’ => $input[‘first_name’],
‘last_name’ => $input[‘last_name’],
];

$new_user = $this->fpdo->insertInto(‘users’, $user)->execute();

return (new Payload)
->withStatus(Payload::OK)
->withOutput([
‘user’ => $new_user,
]);
}
}
[/code]

The above code is very basic and could definitely do with some data validation, but it’ll do just fine for the purposes of this article.

With FluentPDO, we’re able to easily insert or update a record. All you have to do is call the ‘insertInto()’ method with the table you want to insert into and the data in an array. Note that INSERT, UPDATE and DELETE statements won’t be run until you call ‘execute()’ on them.

Now that we have the action created, we can create the route in ‘web/index.php’. Add the following code to the routes area:

[code]
$r->post(‘/user’, ‘Spark\Project\Domain\DoUser’);
[/code]

As you can see, we now use ‘$r->post()’ to specify that the defined Action should be called when something is POST’d to ‘/user’.

Using your favorite tool, make a POST request that contains, “username, first_name and last_name”. The response should be something similar to:

[code]
{“user”:1}
[/code]

The ‘1’ in the response is the user_id that was used when creating or updating the user. This is automatically done by FluentPDO to provide quick access to the identifier.

You should now be able to perform a GET request, passing in the username that you specified previously and it will return JSON output for the entire row of data.

Conclusion

Although this was a very basic article on how to use Spark and FluentPDO, I hope it helped build a ground layer to get you going on building an API. Stay tuned for part 2 where we will expand upon the API.


 

Let's Get Started