Building a simple API using Codeigniter 3
Tags: php, codeigniter, api
Published: 2019-10-21 12:40:09

---
title: Building a simple API using Codeigniter 3
published: true
description: Using PHP7, Codeigniter 3 and MariaDB to build an API to serve SPA applications
tags: php,codeigniter,api

---

Codeigniter is a powerful PHP Framework that are popular because its fast, simple and easy to configure. The version 4 is underway and the version 3 is widely used for web development in all kind of projects. So lets use to create an API and serve single page applications. 

For this example I will use

Apache 2

PHP 7.3 

MariaDB 15.1



Simple Installation

1 - Download the framework at https://api.github.com/repos/bcit-ci/CodeIgniter/zipball/3.1.11 , uncompress the file, rename the folder to 'baseapi'  and put the folder in your server host folder, in my case '/var/www/html' , now, access the URL http://localhost/basepapi, the default framework page should be shown. 

Project Structure and connecting to a database

2 - If you ever had to deal with a MVC framework, Codeigniter folder structure will seem pretty familiar. 

*   application
*   * cache
    * config
    * controllers
    * core
    * helpers
    * hooks
    * language
    * libraries
    * logs
    * models
    * third_party
    * views
*   system



We need to define two constants to expose our model and controllers folder. 

Go to config/constants.php and add this two lines

```  php
define('MODELS_DIR', APPPATH . "models/");
define('CONTROLLERS_DIR', APPPATH . "controllers/");
```

Lets focus on the most used folders config, controllers, models and views and to start lets configure our database connection config/database.php.

Here we assume that you have a working mysql database connection

```  php
$db['default'] = array(
	'dsn'	=> '',
	'hostname' => 'localhost',
	'username' => 'root',
	'password' => 'root',
	'database' => 'baseapi',
	'dbdriver' => 'mysqli',
	'dbprefix' => '',
	'pconnect' => FALSE,
	'db_debug' => (ENVIRONMENT !== 'production'),
	'cache_on' => FALSE,
	'cachedir' => '',
	'char_set' => 'utf8',
	'dbcollat' => 'utf8_general_ci',
	'swap_pre' => '',
	'encrypt' => FALSE,
	'compress' => FALSE,
	'stricton' => FALSE,
	'failover' => array(),
	'save_queries' => TRUE
);

```

 

Now we refresh the page, if no connection errors were shown, we're fine to move on.

3 - Our Base Model 

Lets create our BaseModel.php on models folder. 

``` php
<?php

abstract class BaseModel extends CI_Model
{
    abstract function get_table_name();

    public function persist($data)
    {
        $cleaned_data = $this->sanitize_fields($data, $this->get_table_name());

        if (isset($cleaned_data['id']) && intval($cleaned_data['id']) > 0)
            return $this->update($cleaned_data);

        unset($cleaned_data['id']);

        $this->db->set($cleaned_data);
        $this->db->insert($this->get_table_name());
        return $this->db->insert_id();
    }

    public function update($data)
    {
        $cleaned_data = $this->sanitize_fields($data, $this->get_table_name());
        $this->db->where('id', $cleaned_data['id']);
        return $this->db->update($this->get_table_name(), $cleaned_data);
    }

    public function sanitize_fields($data, $table_name)
    {
        $table_fields = $this->db->list_fields($table_name);
        $posted_fields = array_keys($data);
        foreach ($posted_fields as $posted_field) {
            if (!in_array($posted_field, $table_fields))
                unset($data[$posted_field]);
        }
        return $data;
    }

    function get_by_id($id)
    {
        $this->db->select('*');
        $this->db->from($this->get_table_name());
        $this->db->where('id', $id);
        $query = $this->db->get();
        return $query->result();
    }

    function get_all()
    {
        $this->db->select('*');
        $this->db->from($this->get_table_name());
        $query = $this->db->get();
        return $query->result();
    }
}
```



4 - Controllers

On the folder controllers lets create a new file called BaseController.php 

Codeigniter is primarily a MVC framework so we need to make some modifications to work as a service API. 

Our controller need to deal with GET, PUT, DELETE and POST requests, we need to enable CORS by adding some lines to our constructor. We need also a function to get the input and convert to json, and a default behavior dealing with POST and DELETE REQUEST.

```php
<?php
defined('BASEPATH') or exit('No direct script access allowed');

abstract class BaseController extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method");
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method == "OPTIONS") {
            die();
        }

        $this->load->database();

        $this->persist_or_remove();
    }
    
    public function index(){
        echo 'Hello !';
    }

    public function get_data()
    {
        $json_str = file_get_contents('php://input');
        $data = json_decode($json_str);
        return $data;
    }

    public function persist_or_remove()
    {

        if ($this->is_delete()) {
            $this->remove();
        } elseif ($this->is_post()) {
            $this->persist();
        }
    }

    public function is_get()
    {
        return $_SERVER["REQUEST_METHOD"] === "GET";
    }

    public function is_post()
    {
        return $_SERVER["REQUEST_METHOD"] === "POST";
    }

    public function is_delete()
    {
        return $_SERVER["REQUEST_METHOD"] === "DELETE";
    }

    public function json_response($flag, $msg, $obj)
    {
        $res = (object) array(
            'flag' => $flag,
            'msg' => $msg,
            'obj' => $obj
        );

        return json_encode($res);
    }


    abstract protected function persist();
    abstract protected function remove();
}


```

The default Codeigtniter controller is Welcome.php so  when we access http://localhost/baseapi the controller that deals with the request is the default controller, we need to change it going to config/routes.php and change this line

```php
$route['default_controller'] = 'welcome';
```

to 

```php
$route['default_controller'] = 'BaseController';
```

Now,  access http://localhost/baseapi and if our "Hello !" (the index function) appears we are good to go. 



For last, lets create a controller that inherits the BaseController:

```php
<?php
require_once(CONTROLLERS_DIR . 'BaseController.php');

class Users extends BaseController
{
    public function __construct()
    {
        parent::__construct();
        $this->load->model('user');
    }

    public function index()
    {
        if (parent::is_get()) {
            $response = $this->user->get_all();
            echo parent::json_response(TRUE, "OK", $response);
        }
    }

    public function persist()
    {
        $this->user->persist(parent::get_data());
    }

    public function remove()
    {
        $this->user->remove(parent::get_data());
    }
}

```



Now we can get all users in database by sending a GET request to http://localhost/baseapi/index.php/users, insert and update by sending POST or DELETE. 

Here is the official documentation quote:

<i>CodeIgniter is an Application Development Framework - a toolkit - for people who build web sites using PHP. Its goal is to enable you to develop projects much faster than you could if you were writing code from scratch, by providing a rich set of libraries for commonly needed tasks, as well as a simple interface and logical structure to access these libraries. CodeIgniter lets you creatively focus on your project by minimizing the amount of code needed for a given task.</i>

Repo: https://github.com/cardocha/baseapi-ci3

Reference: https://codeigniter.com/user_guide/index.html