Fork me on GitHub

Getting started.

The way Ginger Framework is setup is to enable you to create an API easily and still giving you the freedom to use whatever packages or datasources you want or need.

It has very little dependancies (only PHP 5.3+ and RainTPL only if you want to use the embedded HTML output format) so getting started is fast and easy.

To start using it you have to complete 4 steps which I'll explain here for you:

1: Create a VHOST on your webserver

To be able to serve whatever your RESTful framework should server all you need to do is point all requests to the index.php. I included an Apache Vhost and a Nginx Config file so you can easily do this.

Apache

Nginx

server {
    listen 80;
    server_name  hostname;

    root /path/to/your/application/public/;

    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_index   index.php;
        fastcgi_pass    127.0.0.1:9000;
        include         fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
    }

    location ~ /\.ht
    {
        deny all;
    }
}

2: Create a skeleton project (or use our example)

To use ginger framework, you need a public directory with an index.php (I recommend putting the application code outside of your public directory) and a module directory. I also recommend putting your working directories in the PHP include path, this makes working with it much easier.

The index file is needed for bootstrapping the app. In the example below it does all you need to run your API with one module ("/" resource).

public/index.php

<?php

// Add the appropiate extra include paths here
$includePaths = array(
    __DIR__."/../vendor/",
    __DIR__."/../modules/"
);

// Add the above paths to the global include path
set_include_path(implode(PATH_SEPARATOR, $includePaths));

// Register the psr-0 autoloader for ease of use 
// and include the vendor/autoload.php for the composer packages
spl_autoload_register(function($c){@include preg_replace('#\\\|_(?!.+\\\)#','/',$c).'.php';}); include 'autoload.php';

// Add a default route
\Ginger\Routes::set("/");

// Load the Request class
$request = new \Ginger\Request();

// Fire the request!
$request->go();

Then, to be able to catch and handle the request, you also need the module code. In the case of the root (= "/") resource. Because this is a "non-filter" request this translates to the INDEX action. So the code to handle this is:

modules/index.php

<?php
// Set the data to the response object
$this->getResponse()->setData(array("it" => "works!"));

And that's it for now.

3: Use composer to install Ginger Framework

To install the Ginger Framework you need composer and add the requirement of the framework to your local composer.json file so it might look something like this (you should not use dev-master in production of course):

{
    "require": {
        "ginger/ginger": "dev-master"
    }
}

And run composer install afterwards.

If step 3 is done you are now able to see something if you check out the resource in a browser (go to http://yourchosenhostname/) and you should see:

{
  "it" : "works!"
}

4: Create your first module

To create a module, you have to do 2 things. The first is create a route. Let's say we want to create the forum posts resource:

\Ginger\Routes::set("/forum/posts");

The second is to create the module directory structure with the action files.

modules/forum/posts/index.php

<?php
// The index action is usually for getting a list
$posts = array(); // Use the db, orm or files of your choosing to actually get data
$total = count($posts);

if($total > 0) {
    // Send the data back to the client
    $this->getResponse()->setData(array("total" => $total, "posts" => $posts));
} else {
    throw new \Ginger\Exception("No posts found", 404); // Send back a 404 because we didn't find anything!
}

modules/forum/posts/get.php

<?php
// The get action is usually for getting a list with filters attached,
// this action is only reached if
// one or more filter parameters are sent in the request

// Get the filters passed by either query parameters or the uri
// This returns a key => value array
$filter = $this->getFilterParameters();

$posts = array();   // Use the db, orm or files of your choosing to actually get data
                    // Maybe you can use a Model where you can input the above filter
                    // to get the data you requested. You are completely free in this
$total = count($posts);

if($total > 0) {
    // Send the data back to the client
    $this->getResponse()->setData(array("total" => $total, "posts" => $posts));
} else {
    throw new \Ginger\Exception("No posts found", 404); // Send back a 404 because we didn't find anything!
}

modules/forum/posts/post.php

<?php
// The post action is usually for creating an item

// Get the data parameters
// This returns a key => value array
$data = $this->getDataParameters();

$ok = true;
$post = array();
$post[] = $data;    // Use the db, orm or files to create/store this file. 
                    // This is just a mock object
                    // You are completely free in this
if($ok === true) { // You should do some validation here, with whatever library you like
    $this->getResponse()->setStatus(201); // Set status code 201 Created
    $this->getResponse()->setData(array("created" => 1, "data" => $data));
} else {
    throw new \Ginger\Exception("Something went wrong!", 400); // Send back a 400 Bad Request error
}

modules/forum/posts/put.php

<?php
// The put action is usually for updating an (one or more) item
// This action can be accompanied with filter parameters to update based
// on id or other filters

// Get the data parameters
// This returns a key => value array
$data = $this->getDataParameters();

// Get the filters passed by either query parameters or the uri
// This returns a key => value array
$filter = $this->getFilterParameters();

$ok = true;
$post = array();    // Use the db, orm or files to update an item
                    // This is just a mock object
                    // You are completely free in this

if($ok === true) { // You should do some validation here, with whatever library you like
    $this->getResponse()->setData(array("updated" => 2, "filters" => $filters, "data" => $data));
} else {
    throw new \Ginger\Exception("Something went wrong!", 400); // Send back a 400 Bad Request error
}

modules/forum/posts/delete.php

<?php
// The delete action is usually for delete an (one or more) item

// Get the filters passed by either query parameters or the uri
// This returns a key => value array
$filter = $this->getFilterParameters();

$ok = true;
$post = array();    // Use the db, orm or files to update an item
                    // This is just a mock object
                    // You are completely free in this

if($ok === true) { // You should do some validation here, with whatever library you like
    $this->getResponse()->setStatus(204); // Send back a 204 No Content status code
    $this->getResponse()->setData(array("deleted" => 2, "filters" => $filters));
} else {
    throw new \Ginger\Exception("Something went wrong!", 400); // Send back a 400 Bad Request error
}

And your done! This resource is now fully available! I recommend you use the Postman application available through the Chrome App Store to test all actions using the right HTTP action.