PHP Routing & Restful API
In this tutorial, we are going to create restful APIs with PHP. The APIs will be accessed by Angular app to fetch products, add, update and delete products from Mysql database.
Now you have to install Composer on your local development machine. Composer is a very helpful tool to manage dependencies in PHP. Here is where you can download Composer: https://getcomposer.org/. Again, if you haven't installed NPM, VSC editor, and XAMPP, visit the Angular & PHP for download links.
In the xampp/htdocs folder of XAMPP, create a folder named mysite. In the mysite folder, create another folder named api. In the api folder, create composer.json file.
This configuration allows you to use App name while namespacing the files instead of app directory. For example, you can specify a namespace like App\Controllers.
Now, the project structure looks like this.
mysite
-api
-composer.json
Then in the api folder, execute the following command to initialize Composer. You will see vendor folder and autoload.php file in it.
composer dump-autoload
In this tutorial, we are going to use symfony to make route system in PHP. Thus, you have to install two packages from symfony: symfony/routing and symfony/http-foundation by executing the following commands:
composer require symfony/routing
composer require symfony/http-foundation
If you check inside the vendor folder, you can see that a new folder called Symfony has been created.
Now, we start creat routing sytem in PHP using Symfony. In the api folder, create four folders: app, config, db, and public folders. So, our project looks like this.
In the config folder, create config.php with the following content:
In the routes folder, create web.php file. The web.php file defines routes for our api. For now, we simply has one route to home page. We will add more routes later.
The add() method of the RouteCollection take two arguments. The first argument is the route name and the second argument is a Route object in which you define route path and array of custom attributes that you want to return when this particular route is matched. Typically, the array would be a combination of the controller and method which you would like to call when this route is requested.
In the app folder, create Controllers folder. Inside the Controllers folder, create HomeController.php file. It simply show "Home Page" message when you access the root of the api.
Now, include the routes engine in the public/index.php file (in public folder) in:
The index.php file is the entry point of our APIs. To tell Apache to redirect all request to the entry point, We create .htaccess file in the api folder and add the following configuration:
In the configuration, we also specify CORS - CROSS-ORIGIN REQUEST HEADERS to allow APIs being accessed from client app (e.g Angular app).
Now start Apache. Then go to web browser and access http://localhost/mysite/api/. You would get "Home Page" message.
Now you have to install Composer on your local development machine. Composer is a very helpful tool to manage dependencies in PHP. Here is where you can download Composer: https://getcomposer.org/. Again, if you haven't installed NPM, VSC editor, and XAMPP, visit the Angular & PHP for download links.
In the xampp/htdocs folder of XAMPP, create a folder named mysite. In the mysite folder, create another folder named api. In the api folder, create composer.json file.
{ "name": "php_api", "description": "PHP APIs", "autoload": { "psr-4": { "App\\": "app/" } } }
This configuration allows you to use App name while namespacing the files instead of app directory. For example, you can specify a namespace like App\Controllers.
Now, the project structure looks like this.
mysite
-api
-composer.json
Then in the api folder, execute the following command to initialize Composer. You will see vendor folder and autoload.php file in it.
composer dump-autoload
In this tutorial, we are going to use symfony to make route system in PHP. Thus, you have to install two packages from symfony: symfony/routing and symfony/http-foundation by executing the following commands:
composer require symfony/routing
composer require symfony/http-foundation
If you check inside the vendor folder, you can see that a new folder called Symfony has been created.
Now, we start creat routing sytem in PHP using Symfony. In the api folder, create four folders: app, config, db, and public folders. So, our project looks like this.
mysite
-api
-composer.json
-api
-composer.json
-app
-config
-db
-db
-public
<?php //App Root define('APP_ROOT', dirname(dirname(__FILE__))); define('URL_ROOT', '/mysite'); // sub folder define('URL_SUBFOLDER', '/api');
In the routes folder, create web.php file. The web.php file defines routes for our api. For now, we simply has one route to home page. We will add more routes later.
<?php use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; // Routes collection $routes = new RouteCollection();
// add route to the collection
$routes->add('homepage', new Route(constant('URL_SUBFOLDER') . '/', array('controller' => 'HomeController', 'method'=>'indexAction'), array()));
The add() method of the RouteCollection take two arguments. The first argument is the route name and the second argument is a Route object in which you define route path and array of custom attributes that you want to return when this particular route is matched. Typically, the array would be a combination of the controller and method which you would like to call when this route is requested.
In the app folder, create Router.php file. The Router.php checks if the routes defined in routes/web.php exist and calls method of the right controller.
<?php namespace App; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\NoConfigurationException; class Router { public function __invoke(RouteCollection $routes) { $context = new RequestContext(); $request = Request::createFromGlobals(); $context->fromRequest(Request::createFromGlobals()); // Routing can match routes with incoming requests $matcher = new UrlMatcher($routes, $context); try { $matcher = $matcher->match(substr($_SERVER['REQUEST_URI'],strlen(URL_ROOT))); // Cast params to int if numeric array_walk($matcher, function(&$param) { if(is_numeric($param)) { $param = (int) $param; } }); $className = '\\App\\Controllers\\' . $matcher['controller']; $classInstance = new $className(); // Add routes as paramaters to the next class $params = array_merge(array_slice($matcher, 2, -1), array('routes' => $routes)); // call method of the right controller call_user_func_array(array($classInstance, $matcher['method']), $params); } catch (MethodNotAllowedException $e) { echo 'Route method is not allowed.'; } catch (ResourceNotFoundException $e) { echo 'Route does not exists.'.$e; } catch (NoConfigurationException $e) { echo 'Configuration does not exists.'; } } } // Invoke $router = new Router(); $router($routes);
In the app folder, create Controllers folder. Inside the Controllers folder, create HomeController.php file. It simply show "Home Page" message when you access the root of the api.
<?php namespace App\Controllers; use App\Models\Product; use Symfony\Component\Routing\RouteCollection; class HomeController { // Homepage action public function indexAction(RouteCollection $routes) { echo 'Home Page'; } }
Now, include the routes engine in the public/index.php file (in public folder) in:
<?php // autoload require_once '../vendor/autoload.php'; // Load Config require_once '../config/config.php'; // Routes require_once '../routes/web.php'; require_once '../app/Router.php'; ?>
The index.php file is the entry point of our APIs. To tell Apache to redirect all request to the entry point, We create .htaccess file in the api folder and add the following configuration:
RewriteEngine On # Stop processing if already in the /public directory RewriteRule ^public/ - [L] # Static resources if they exist RewriteCond %{DOCUMENT_ROOT}/public/$1 -f RewriteRule (.+) public/$1 [L] # Route all other requests RewriteRule (.*) public/index.php?route=$1 [L,QSA] # Set the headers for the restful api Header always set Access-Control-Allow-Origin * Header always set Access-Control-Max-Age "1000" Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding" Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
In the configuration, we also specify CORS - CROSS-ORIGIN REQUEST HEADERS to allow APIs being accessed from client app (e.g Angular app).
Now start Apache. Then go to web browser and access http://localhost/mysite/api/. You would get "Home Page" message.
Comments
Post a Comment