PHP REST – Designing an Application to Use REST

ArchitecturemvcPHPrest

I'm not sure how to ask this. I know this is simplistic, but I understand (I think):

  • REST is an architecture, not required, simply a way to build
  • REST is a style and a community standard for transfer of data
  • REST uses verbs and nouns, mostly the latter, GET, POST, PUT,
    DELETE…

As I read I only see the architecture from the consumers point of view and the creator of the API for the consumer.

What I cannot find is how to do this for just my application. What if I'm not sharing anything with anyone at the moment. I want to build my application to follow this architecture for the future.

What do I do now? If I want to use this type of construct:

Examples:

  • PUT http://www.example.com/customers/12345
  • PUT http://www.example.com/customers/12345/orders/98765
  • PUT http://www.example.com/buckets/secret_stuff

I my application, when I create a new person, I use an HTML <form action="something.php" method=POST> Now how do I do this with PUT? Where does this go?

If I use http://www.example.com/customers/12345 how do I know within my application that I want to PUT or GET or whatever?

I'm using MVC, where's my action? I realize the consumer might use my architecture/service with nouns, but this is for only me. How do I know what to do, if I can't use PUT in a form tag?

Right now I use my PHP page to grab the query string based upon a RewriteRule:

require_once("database\\adapters\\PDO\\Database.bootstrap.php");
class App {
    protected $_controller = 'Welcome';
    protected $_method = 'index';
    protected $_params = [];
    protected $_model = 'Welcome';

    public function __construct(){
    $url = $this->parseURL();
    //This works because I put the rewrite rules in IIS; 
    //Our RewriteRule in IIS (or Apache) is ^(.+)$  This is any character saved to a variable.
    //The new location is index.php?url=$1 [QSA, L].  This will look a little different after you import it into IIS.

    if (file_exists('app\\controllers\\' . $url[0] . '.controller.php')){
        $this->_controller = $url[0];
        $this->_model = $url[0];
        unset($url[0]);  //Unset removes that element from the array; 
        //var_dump($url);
    }

    //Get the controller and model.  All done by convention over configuration;
    require_once 'app\\controllers\\' . $this->_controller . '.controller.php';
    require_once 'app\\models\\Parent.model.php';

    //get a new Database object from the bootstrap;
    $_DB = new DatabaseBootstrap();

    $this->_controller = $this->_controller . "Controller"; 

    $this->_model = new ParentModel($_DB->getAdapter());
    $this->_controller = new $this->_controller($this->_model);

    //This checks to see if our method from the url exists;
    //Your querystring will look like this - http://server/virtualdirectory/controller/action/variables1/variable2.....

    if(isset($url[1])){
        if(method_exists($this->_controller,$url[1])){
            $this->_method = $url[1];
            unset($url[1]);
        }
    }

    $this->_params = $url ? array_values($url) : [];

    //This calls your controller and your method and sends over your array of parameters
    call_user_func_array([$this->_controller, $this->_method],$this->_params)
}

public function parseURL(){
    if(isset($_GET['url'])){
        return $url = explode('/',filter_var(rtrim($_GET['url'],'/'),FILTER_SANITIZE_URL));
        }
    }

EDIT: Based upon my reading of the answers, it appears I cannot use REST natively as in using HTTP verbs. I either have to use the name of the types in AJAX or I have to have a hidden field that contains my REST method like so (example from cakePHP):

<form id="RecipeEditForm" method="post" action="/recipes/edit/5">
<input type="hidden" name="_method" value="PUT" />

And it seems this is done for the "greater good." That is, so that others can consume my API services using libraries such as curl or using AJAX where one can create any request method they wish (?). Since we are using a REST architecture, the consumer using the API would simply put PUT, DELETE, etc. Some future architecture might not use those verbs, so we make up new keywords. It's just that PUT, etc. are in the w3 specs for HTTP, which are not very well supported.?

Best Answer

One popular php framework allows faking PUT/DELETE requests by adding a _method=PUT argument to your form action:

<form method="POST" action="/customers/12345?_method=PUT">

Internally, the framework converts the POST request to a PUT request.

http://symfony.com/doc/current/cookbook/routing/method_parameters.html#faking-the-method-with-method

Easy enough to implement. But I would follow @vrostu's advice and look into a javascript REST framework instead of trying to use forms.

Related Topic