Writing a RESTful Web Service with Slim

Share this article

Through a series of articles
here at SitePoint you’ve learned about what is REST and how it works. In this article, I’d like to show you how to create a RESTful web service using Slim, a PHP micro-framework inspired by Sinatra, a Ruby framework. It’s well-suited for creating simple RESTful web services and comes with some minimal components like Router, Request, Response, and View. It’s very simple, and is easy to understand and use.

Say Hello to Slim World

To get started with Slim, you’ll need to download it first. It requires PHP 5.2+ and lets you write applications in both procedural style or in 5.3+ style, e.g. using anonymous functions. In this article I’ll be using 5.3 style coding for all examples, assuming you are already familiar with it. To create a Hello World application, remove the default index.php file in the application directory and create a new index.php file with the following code:
<?php
require "Slim/Slim.php";

// create new Slim instance
$app = new Slim();

// add new Route 
$app->get("/", function () {
    echo "<h1>Hello Slim World</h1>";
});

// run the Slim app
$app->run();
Your first Slim application is ready now. If you access index.php through your browser, you should see a big “Hello Slim World.” To use Slim in your applications, you need to include Slim.php and Slim will autoload all of the other files that it needs. Then you can create one or more instances of the Slim object and add your routes. The Slim constructor accepts an array of application configuration values. MODE, TEMPLATES.PATH and VIEW are some important configurations that we often use. Use MODE to set the application environment to be used, like development or production. TEMPLATES.PATH sets the location to use for template files. Slim uses Slim_View to render the view by default, but you can write custom view handlers and attach them to Slim by using the VIEW value. The following example shows how to to create a new Slim instance with a custom TEMPLATES.PATH and sets the environment to development mode.
<?php
$app = new Slim(array(
    "MODE" => "development",
    "TEMPLATES.PATH' => "./templates"
));
The most important part of creating an application using Slim is creating routes. A route helps to map a URI to a callback function for specific request methods. Slim provides a simple and intuitive way to map the same URIs with different requests methods. It will invoke the first callback function that matches the current URI and request method, or produce a 404 error if it is unable to match. After adding the routes, you need to call the run() method on the Slim
instance to run the application.

Writing a Library Service

As a more in-depth exercise, let’s create a simple Library management web service application using Slim. In this application we’ll be able to list, add, delete, and update book details using web service calls. The following table lists the endpoints that will be supported by the web service: For database interactions, I’ll use NotORM, a PHP library written by Jakub Vrána as an alternative to ORM which provides a simple and intuitive API to work with data from your database. NotORM uses PHP’s PDO extension to access the database, and so a PDO instance is passed to NotORM‘s constructor.
<?php
require "NotORM.php";

$pdo = new PDO($dsn, $username, $password);
$db = new NotORM($pdo);

Listing Books

The first endpoint lists all of the books in the library, so let’s use Slim to create the endpoint and return the data encoded in JSON format.
<?php
...
$app = new Slim(
    "MODE" => "developement",
    "TEMPLATES.PATH' => "./templates"
);

$app->get("/books", function () use ($app, $db) {
    $books = array();
    foreach ($db->books() as $book) {
        $books[]  = array(
            "id" => $book["id"],
            "title" => $book["title"],
            "author" => $book["author"],
            "summary" => $book["summary"]
        );
    }
    $app->response()->header("Content-Type", "application/json");
    echo json_encode($books);
});
get() is a Slim method that routes to a GET request on the given URI. It’s first argument is the URI and last argument is a callback function. The use keyword enables us to access the outer variables from inside the scope of the anonymous function. Within the function, we create an array of books by looping through each record returned by the database ($db->books() returns a traversable reference to the books table). The response’s Content-Type header is sent as “application/json” and we emit the encoded array of book data. Now let’s write the endpoint for getting the details of a book with a given ID:
<?php
...
$app->get("/book/:id", function ($id) use ($app, $db) {
    $app->response()->header("Content-Type", "application/json");
    $book = $db->books()->where("id", $id);
    if ($data = $book->fetch()) {
        echo json_encode(array(
            "id" => $data["id"],
            "title" => $data["title"],
            "author" => $data["author"],
            "summary" => $data["summary"]
            ));
    }
    else{
        echo json_encode(array(
            "status" => false,
            "message" => "Book ID $id does not exist"
            ));
    }
});
Here we have added a parameter to Route for passing the ID of the book. While executing this route, Slim will invoke the callback function with the value for the parameter as an argument. Note that the parameter is mandatory. You can make it optional by placing it inside a parenthesis like: /book(/:id) If you are making a parameter optional, though, you won’t be able to specify parameters for the callback function. In that case you can make use of the func_get_args() function to get any arguments passed to the callback.

Adding and Editing Books

Now let’s address the endpoints responsible for adding and updating book information. We’ll use the post()
method to add new data, and put() to update existing data.
<?php
...
$app->post("/book", function () use($app, $db) {
    $app->response()->header("Content-Type", "application/json");
    $book = $app->request()->post();
    $result = $db->books->insert($book);
    echo json_encode(array("id" => $result["id"]));
});

$app->put("/book/:id", function ($id) use ($app, $db) {
    $app->response()->header("Content-Type", "application/json");
    $book = $db->books()->where("id", $id);
    if ($book->fetch()) {
        $post = $app->request()->put();
        $result = $book->update($post);
        echo json_encode(array(
            "status" => (bool)$result,
            "message" => "Book updated successfully"
            ));
    }
    else{
        echo json_encode(array(
            "status" => false,
            "message" => "Book id $id does not exist"
        ));
    }
});
$app->request() returns the current request object (Slim_Http_Request) with POST or PUT data. You can get the POST values using the post() method of this object, and the PUT values using the put() method. Here we’re assuming both POST and PUT data is key/value pairs of information with table column names as keys. In a real-world application, you will need to add some validation and error handling, but I’ve omitted it here for the sake of simplicity. If you plan on accessing your Slim application from a browser, you won’t be able to easily make PUT requests, as browsers don’t normally expose the method via HTML. To overcome this, Slim have a provision that let’s you override POST requests to PUT by placing a hidden field in your form. The field’s name should be “_METHOD” and the value set to “PUT”.
<form action="#" method="post">
 <input type="hidden" name="_METHOD" value="PUT">
 Title: <input type="text" name="title"><br>
 Author: <input type="text" name="author"><br>
 Summary: <textarea name="summary"></textarea>
 <br>
 <input type="submit" value="Submit">
</form>

Deleting Books

Now that we have the endpoints to add, edit, and list books in our web service, the next obvious thing we need to is the endpoint to delete books. It should accept the ID of book to be deleted and remove the corresponding record from the database.
<?php
...
$app->delete("/book/:id", function ($id) use($app, $db) {
    $app->response()->header("Content-Type", "application/json");
    $book = $db->books()->where("id", $id);
    if ($book->fetch()) {
        $result = $book->delete();
        echo json_encode(array(
            "status" => true,
            "message" => "Book deleted successfully"
        ));
    }
    else{
        echo json_encode(array(
            "status" => false,
            "message" => "Book id $id does not exist"
        ));
    }
});
Everything is pretty straightforward here. First we fetch the row corresponding to the given ID from the database, just like we have done when getting book details earlier. Calling the delete() method on the row object will delete that record from database. We have created all the necessary endpoints related to books. In some cases you may want to have a single route that will respond to more than one request methods. It can be implemented using the map() method of Slim, which is explained here.

Summary

In this article we’ve discussed creating a RESTful web service using the Slim framework. Now you should be able to create your own web service applications without much trouble. Of course, there are many more things you can do than the simple things discussed here. You can have routes with many parameters, data validation, and so on. So dig into it and use tools like Slim and NoORM to help you achieve your objectives. You can download the source code of this article from GitHub. Image via Fotolia

Frequently Asked Questions (FAQs) about Writing a RESTful Web Service with Slim

What is Slim and why is it used for creating RESTful web services?

Slim is a PHP micro-framework that is often used to create RESTful APIs and web services. It is lightweight, easy to understand, and comes with a sophisticated URL router and middleware architecture that makes it ideal for these tasks. Slim’s simplicity and flexibility allow developers to quickly create and maintain web services, making it a popular choice for many.

How do I install Slim for creating a RESTful web service?

To install Slim, you need to have Composer installed on your system. Composer is a tool for dependency management in PHP. Once you have Composer, you can install Slim by running the command composer require slim/slim "^3.0". This will install Slim and its dependencies in your project directory.

How do I create routes in Slim?

In Slim, you can create routes by defining them in your application. A route is essentially a path or a URL pattern. For example, to create a GET route, you would use the get method on your Slim app instance like this: $app->get('/hello/{name}', function (Request $request, Response $response, array $args) { return $response; });. This creates a route ‘/hello/{name}’ where ‘{name}’ is a placeholder for any name you pass in the URL.

What is Middleware in Slim and how is it used?

Middleware in Slim is a powerful feature that allows you to manipulate the Request and Response objects in your application. It can be used for a variety of tasks such as authentication, caching, and more. Middleware is added to the application by calling the add method on the Slim app instance and passing in your middleware.

How do I handle errors in Slim?

Slim comes with a built-in error handler that you can use to handle exceptions and errors in your application. You can also create custom error handlers by defining a middleware that catches exceptions. This allows you to handle errors in a way that suits your application’s needs.

How do I send responses in Slim?

In Slim, you send responses by returning a Response object from your route or middleware. You can modify the Response object by calling its methods. For example, you can set the status code, headers, and body of the response.

How do I retrieve data from the Request object in Slim?

You can retrieve data from the Request object in Slim by calling its methods. For example, you can use the getParam method to retrieve a parameter from the request. You can also use the getParsedBody method to retrieve the parsed body of the request.

How do I use Dependency Injection in Slim?

Slim supports Dependency Injection through its built-in container. You can add dependencies to the container and then retrieve them in your routes or middleware. This makes it easy to manage and share dependencies across your application.

How do I serve static files in Slim?

Serving static files in Slim can be achieved by creating a route that matches the file’s path and then returning the file in the response. However, it’s generally recommended to use a web server like Apache or Nginx to serve static files for better performance.

How do I test my Slim application?

Testing a Slim application can be done using various PHP testing tools like PHPUnit. You can write tests for your routes and middleware and then run them using the testing tool. This helps ensure that your application is working as expected.

Shameer CShameer C
View Author

Shameer is a passionate programmer and open-source enthusiast from Kerala, India. He has experience in web development using Scala, PHP, Ruby, MySQL, and JavaScript. While not working, Shameer spends his time coding personal projects, learning, watching screen casts, blogging, etc. His specific areas of interest include cloud computing, and system and database administration.

Expert
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week