phalcon / cphalcon

High performance, full-stack PHP framework delivered as a C extension.
https://phalcon.io
BSD 3-Clause "New" or "Revised" License
10.78k stars 1.97k forks source link

phalcon - Tutorial 3: Creating a Simple REST API #1437

Closed ohara2 closed 10 years ago

ohara2 commented 10 years ago

Hello,

I try to create a simple REST API from official docs. The file structure looks that: my-rest-api/ models/ Robots.php index.php .htaccess

My question is where/how I should name the files listed below i.e. Retrieving Data...etc. ., should they goes to index.php or Robots.php, documentation is very difficult for a beginner! Tutorial is below: and link:http://docs.phalconphp.com/en/latest/reference/tutorial-rest.html

Creating the Application¶ As the application is so simple, we will not implement any full MVC environment to develop it. In this case, we will use a micro application to meet our goal.

The following file structure is more than enough:

my-rest-api/ models/ Robots.php index.php .htaccess First, we need an .htaccess file that contains all the rules to rewrite the URIs to the index.php file, that is our application:

RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L]

Then, in the index.php file we create the following:

<?php

$app = new \Phalcon\Mvc\Micro();

//define the routes here

$app->handle(); Now we will create the routes as we defined above:

<?php

$app = new Phalcon\Mvc\Micro();

//Retrieves all robots $app->get('/api/robots', function() {

});

//Searches for robots with $name in their name $app->get('/api/robots/search/{name}', function($name) {

});

//Retrieves robots based on primary key $app->get('/api/robots/{id:[0-9]+}', function($id) {

});

//Adds a new robot $app->post('/api/robots', function() {

});

//Updates robots based on primary key $app->put('/api/robots/{id:[0-9]+}', function() {

});

//Deletes robots based on primary key $app->delete('/api/robots/{id:[0-9]+}', function() {

});

$app->handle(); Each route is defined with a method with the same name as the HTTP method, as first parameter we pass a route pattern, followed by a handler. In this case, the handler is an anonymous function. The following route: ‘/api/robots/{id:[0-9]+}’, by example, explicitly sets that the “id” parameter must have a numeric format.

When a defined route matches the requested URI then the application executes the corresponding handler.

Creating a Model¶ Our API provides information about ‘robots’, these data are stored in a database. The following model allows us to access that table in an object-oriented way. We have implemented some business rules using built-in validators and simple validations. Doing this will give us the peace of mind that saved data meet the requirements of our application:

<?php

use Phalcon\Mvc\Model, Phalcon\Mvc\Model\Message, Phalcon\Mvc\Model\Validator\InclusionIn, Phalcon\Mvc\Model\Validator\Uniqueness;

class Robots extends Model {

public function validation()
{
    //Type must be: droid, mechanical or virtual
    $this->validate(new InclusionIn(
        array(
            "field"  => "type",
            "domain" => array("droid", "mechanical", "virtual")
        )
    ));

    //Robot name must be unique
    $this->validate(new Uniqueness(
        array(
            "field"   => "name",
            "message" => "The robot name must be unique"
        )
    ));

    //Year cannot be less than zero
    if ($this->year < 0) {
        $this->appendMessage(new Message("The year cannot be less than zero"));
    }

    //Check if any messages have been produced
    if ($this->validationHasFailed() == true) {
        return false;
    }
}

} Now, we must set up a connection to be used by this model:

<?php

$di = new \Phalcon\DI\FactoryDefault();

//Set up the database service $di->set('db', function(){ return new \Phalcon\Db\Adapter\Pdo\Mysql(array( "host" => "localhost", "username" => "asimov", "password" => "zeroth", "dbname" => "robotics" )); });

//Create and bind the DI to the application $app = new \Phalcon\Mvc\Micro($di); Retrieving Data¶ The first “handler” that we will implement is which by method GET returns all available robots. Let’s use PHQL to perform this simple query returning the results as JSON:

<?php

//Retrieves all robots $app->get('/api/robots', function() use ($app) {

$phql = "SELECT * FROM Robots ORDER BY name";
$robots = $app->modelsManager->executeQuery($phql);

$data = array();
foreach ($robots as $robot) {
    $data[] = array(
        'id' => $robot->id,
        'name' => $robot->name,
    );
}

echo json_encode($data);

}); PHQL, allow us to write queries using a high-level, object-oriented SQL dialect that internally translates to the right SQL statements depending on the database system we are using. The clause “use” in the anonymous function allows us to pass some variables from the global to local scope easily.

The searching by name handler would look like:

<?php

//Searches for robots with $name in their name $app->get('/api/robots/search/{name}', function($name) use ($app) {

$phql = "SELECT * FROM Robots WHERE name LIKE :name: ORDER BY name";
$robots = $app->modelsManager->executeQuery($phql, array(
    'name' => '%' . $name . '%'
));

$data = array();
foreach ($robots as $robot) {
    $data[] = array(
        'id' => $robot->id,
        'name' => $robot->name,
    );
}

echo json_encode($data);

}); Searching by the field “id” it’s quite similar, in this case, we’re also notifying if the robot was found or not:

<?php

//Retrieves robots based on primary key $app->get('/api/robots/{id:[0-9]+}', function($id) use ($app) {

$phql = "SELECT * FROM Robots WHERE id = :id:";
$robot = $app->modelsManager->executeQuery($phql, array(
    'id' => $id
))->getFirst();

//Create a response
$response = new Phalcon\Http\Response();

if ($robot == false) {
    $response->setJsonContent(array('status' => 'NOT-FOUND'));
} else {
    $response->setJsonContent(array(
        'status' => 'FOUND',
        'data' => array(
            'id' => $robot->id,
            'name' => $robot->name
        )
    ));
}

return $response;

}); Inserting Data¶ Taking the data as a JSON string inserted in the body of the request, we also use PHQL for insertion:

<?php

//Adds a new robot $app->post('/api/robots', function() use ($app) {

$robot = $app->request->getJsonRawBody();

$phql = "INSERT INTO Robots (name, type, year) VALUES (:name:, :type:, :year:)";

$status = $app->modelsManager->executeQuery($phql, array(
    'name' => $robot->name,
    'type' => $robot->type,
    'year' => $robot->year
));

//Create a response
$response = new Phalcon\Http\Response();

//Check if the insertion was successful
if ($status->success() == true) {

    $robot->id = $status->getModel()->id;

    $response->setJsonContent(array('status' => 'OK', 'data' => $robot));

} else {

    //Change the HTTP status
    $response->setStatusCode(500, "Internal Error");

    //Send errors to the client
    $errors = array();
    foreach ($status->getMessages() as $message) {
        $errors[] = $message->getMessage();
    }

    $response->setJsonContent(array('status' => 'ERROR', 'messages' => $errors));
}

return $response;

}); Updating Data¶ The data update is similar to insertion. The “id” passed as parameter indicates what robot must be updated:

<?php

//Updates robots based on primary key $app->put('/api/robots/{id:[0-9]+}', function($id) use($app) {

$robot = $app->request->getJsonRawBody();

$phql = "UPDATE Robots SET name = :name:, type = :type:, year = :year: WHERE id = :id:";
$status = $app->modelsManager->executeQuery($phql, array(
    'id' => $id,
    'name' => $robot->name,
    'type' => $robot->type,
    'year' => $robot->year
));

//Create a response
$response = new Phalcon\Http\Response();

//Check if the insertion was successful
if ($status->success() == true) {
    $response->setJsonContent(array('status' => 'OK'));
} else {

    //Change the HTTP status
    $response->setStatusCode(500, "Internal Error");

    $errors = array();
    foreach ($status->getMessages() as $message) {
        $errors[] = $message->getMessage();
    }

    $response->setJsonContent(array('status' => 'ERROR', 'messages' => $errors));
}

return $response;

}); Deleting Data¶ The data delete is similar to update. The “id” passed as parameter indicates what robot must be deleted:

<?php

//Deletes robots based on primary key $app->delete('/api/robots/{id:[0-9]+}', function($id) use ($app) {

$phql = "DELETE FROM Robots WHERE id = :id:";
$status = $app->modelsManager->executeQuery($phql, array(
    'id' => $id
));

//Create a response
$response = new Phalcon\Http\Response();

if ($status->success() == true) {
    $response->setJsonContent(array('status' => 'OK'));
} else {

    //Change the HTTP status
    $response->setStatusCode(500, "Internal Error");

    $errors = array();
    foreach ($status->getMessages() as $message) {
        $errors[] = $message->getMessage();
    }

    $response->setJsonContent(array('status' => 'ERROR', 'messages' => $errors));

}

return $response;

});

phalcon commented 10 years ago

Hi, Github is only intended to report bugs or discuss new features, please open a thread in the forum (http://forum.phalconphp.com/) so someone in the community could help you. Thanks