Build REST API With Yii2

yii provides a whole set of tools to simplify the task of implementing RESTful Web Service APIs. Here I am goint build an example REST APIs with yii2. Lets get started.

  1. open phpstorm, create an empty project, and initial composer.
  2. Open cmd, locate to project folder
  3. Run following two composer commends:

    composer global require “fxp/composer-asset-plugin:^1.2.0”
    composer create-project –prefer-dist yiisoft/yii2-app-basic basic

    If you need learn more about composer, checkout: https://getcomposer.org/

  4. Now upload whole project to the server

    App Store

  5. Change the ownership of the website folder

    cd /home/wwwroot/project1.abc.com
    chown www:www ./ -R

  6. Open the browser

    App Store

  7. Database connection

    App Store

  8. Configure the url manager

    App Store

    App Store

  9. Now we can generate model class by Gii. Open the url:
    http://project1.abc.com/basic/web/index.php?r=gii

    App Store

    We have customer table, just use this table

    App Store

    App Store

    App Store

  10. Use this model as the model of our controller

    App Store

  11. Make a request

    App Store

    App Store

Understand Php Autoload

Let us do little research on the loader mechanism of PHP project. Loader mechanism is the method to load these PHP files the main program need to use

how these old PHP projects load base classes and functional classes.

  1. Opencart 1.5.6.3

    In the index.php of opencart 1.5.6.3, we can find the following statement near the top of few lines

    require_once(DIR_SYSTEM . ‘startup.php’);

    DIR_SYSTEM is a constant which defined in config.php, and the value the path of system folder on server

    The following code is part of the file upload/system/startup.php

// Helper
require_once(DIR_SYSTEM . 'helper/json.php'); 
require_once(DIR_SYSTEM . 'helper/utf8.php'); 

// Engine
require_once(DIR_SYSTEM . 'engine/action.php'); 
require_once(DIR_SYSTEM . 'engine/controller.php');
require_once(DIR_SYSTEM . 'engine/front.php');
require_once(DIR_SYSTEM . 'engine/loader.php'); 
require_once(DIR_SYSTEM . 'engine/model.php');
require_once(DIR_SYSTEM . 'engine/registry.php');

// Common
require_once(DIR_SYSTEM . 'library/cache.php');
require_once(DIR_SYSTEM . 'library/url.php');
require_once(DIR_SYSTEM . 'library/config.php');
require_once(DIR_SYSTEM . 'library/db.php');
require_once(DIR_SYSTEM . 'library/document.php');
require_once(DIR_SYSTEM . 'library/encryption.php');
require_once(DIR_SYSTEM . 'library/image.php');
require_once(DIR_SYSTEM . 'library/language.php');
require_once(DIR_SYSTEM . 'library/log.php');
require_once(DIR_SYSTEM . 'library/mail.php');
require_once(DIR_SYSTEM . 'library/pagination.php');
require_once(DIR_SYSTEM . 'library/request.php');
require_once(DIR_SYSTEM . 'library/response.php');
require_once(DIR_SYSTEM . 'library/session.php');
require_once(DIR_SYSTEM . 'library/template.php');
require_once(DIR_SYSTEM . 'library/openbay.php');
require_once(DIR_SYSTEM . 'library/ebay.php');
require_once(DIR_SYSTEM . 'library/amazon.php');
require_once(DIR_SYSTEM . 'library/amazonus.php');

There are a lots of require_once statement to include the base class and module class there. What we should do if we want to add a library class? First, we should write that file under system\library folder, then we add another requirement_once statement in upload/system/startup.php.

  1. Wordpress

    Wordpress is not object oriented system. I haven’t plan to analysis the implementation of this system deeply. We only focus on the loader part.

    after open the wp-settings.php file under the root folder of Wordpress, we can see the code show shows below.

    App Store

    The wordpress have lots of require statement, and the require statement distributed very diverse.

    Secondly, are there better way to load file when system startup?
    Answer is yes. PHP 5.3+ provides a SPL function to register customized loader function. After we registered the loader function, PHP will call the function to load file when php notice there is a class haven’t loaded.

    Index.php
    <?php

    function autoloader($class) {
      include 'lib/' . $class . '.php';
    }
    
    spl_autoload_register('autoloader');
    
    $a = new A();
    $out = $a->plus(1,2);
    echo $out;
    
    lib/A.php
    

    <?php

    class A{

    public function plus($a, $b){
      return $a + $b;
    }
    

    }

    App Store

    We will get 3 after executed this program. The autoloader function automatically called to load class A. The load rule depends on how we want to locate the file path.

    Finally, all the new PHP projects use this way to load php file on startup, such as, YII2, Laravel, and Drupal 8.

Basic Usage of Redis

Redis is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker. Due to it is fast speed in storing and fetch data, it is widely used as a cache system in web applications. Lets see how it is used in a php example project.

<?php
  //connect to redis
  $redis = new Redis();
  $status = $redis->connect('127.0.0.1', 6379);

  if($status){
    echo "Connection to server sucessfully";
    echo "Server is running: " . $redis->ping();
  } else{
    echo "Connection to server failed";
  }


  Once connected, the connect method will return true;

List operation

Push element to a list :   lPush
Pop element from a list:  lPop
Get element from a list:  lGet
Length of the list:         ILen

    <?php

       error_reporting(E_ALL);
       ini_set('display_errors', 1);

       //connect to redis
       $redis = new Redis();
       $status = $redis->connect('127.0.0.1', 6379);

       if($status){
         echo "Connection to server sucessfully\n";
       }else{
         echo "Connection to server failed\n";
       }

       $redis->delete('list1');

       //list
       $redis->lPush('list1', '1');
       $redis->lPush('list1', '2');
       $redis->lPush('list1', '3');
       $redis->lPush('list1', '4');

       for($i = 0; $i < 4; $i++){
         $result = $redis->lGet('list1', $i);
         echo "element in postion " . $i ." : ". $result . "\n";
       }

       $result = $redis->lPop('list1');
       echo "poped element : " . $result . "\n";

       //get the length of the list
       $result = $redis->lLen('list1');
       echo "length of the list : " . $result . "\n";

       //get the size of the list
      $result = $redis->lSize('list1');
      echo "size of the list : " . $result . "\n";

Hash Map

add element to a hash table :   hSet
get element from a hash table:  hGet
does a key exists?:  hExists
Length of the hash table:         hLen

   //hash map
   $redis->hSet("hash1", "abc", 1);
   $redis->hSet("hash1", "mvp", 2);
   $redis->hSet("hash1", "vip", 3);

   $result = $redis->hGet('hash1', "abc");
   echo "hash element abc: " . $result . "\n";
   $result = $redis->hGet('hash1', "mvp");
   echo "hash element abc: " . $result . "\n";
   $result = $redis->hGet('hash1', "vip");
   echo "hash element abc: " . $result . "\n";

   $result = $redis->hExists('hash1', "vip");
   echo "hash element abc exists? " . $result . "\n";
   $result = $redis->hExists('hash1', "tip");
   echo "hash element abc exists? " . $result . "\n";

   $result = $redis->hLen('hash1');
   echo "hash table abc length: " . $result . "\n";