Thursday 28 May 2020

Basic Things to take care when Upgrading from Codeigniter- 3 to Codeigniter-4

Now a big hurdle for all codeigniter developers around the world is to change their projects from CI-3 to CI-4. Now Codeigniter team has changed there formats and structure in such a way that , developers cannot auto-update just  their versions from 3 to 4. They have to manually edit the code and make changes to the code. . So in this article I am going to explain about some of the basic differences in calling functions between the two versions. Here am giving some examples only. For detailed project code and examples, am going to write another post for that in the coming days. For having a peek overview on the changes have a look into these points explained. iam sure someone will get benefit from this article.

1) Folder Structure

Codeigniter-3 

In codeigniter-3, we have a folder called application, under which all the config, controllers, models, views is placed . In this version codeigniter doesn't restricted us for putting our css, js in any folders. Instead we can place it in any folders in the root and we can access it from our views.

Codeigniter-4

In Codeigniter-4, the application folder has been renamed as app. Now there is a folder called public, in it now we have to put all our css, js and all. Now when we access base_url from the views to access this public folder. This feature, Codeigniter team created mainly for security purpose, so that anything outside the public folder cannot be accessed by intruders. Another thing  in this versionis the usage of too many namespaces. so we can access all folders in root in our models and controllers by defining the namespaces. 

2)Routing

Codeigniter-3

Route File is found in application/config/routes.php

$route['cms/list'] = "cms/list";
Here when request comes for domain.com/cms/list/ it will redirect to CMS controller and run the list method in it.
$route['cms/edit/(:any)'] = "cms/edit/$1";
Here when request comes for domain.com/cms/edit/3 , it will redirect to CMS controller and run edit method in it . then passes $id argument into it.

Codeigniter-4

Route File is Found in app/Config/Routes.php

$routes->add('cms/create/', 'Cms::create');
Here you can see route file configuration is little changed. Here Controller,method is designated as Controller::method format  and another change is you have to mention the submission method. If you see, this is actually a  a add form, so you have to create method for accepting post requests. For post methods, we have to do like adding $routes-> add(). For get method please refer for cms/list down.

$routes->add('cms/edit/(:any)', 'Cms::edit/$1');

Here when the request comes for domain/cms/edit/3 , it will call the CMS controller and execute edit function in it passing the $id as parameter.As edit also is a form, which is submitting post parameters, we have to define it as Post function in the route. so we will add as $routes->add();

$routes->get('cms/list/', 'Cms::list');

This is a list function. It is taking only get arguments. so we will configure it as a get method in the route. So we have to add the rule like $routes->get(). So when request comes for domain.com/cms/list/, it will call the CMS controller and execute the list function defined in it.


3) USING CUSTOM NAMESPACES

This is one of the mighty enhancements done by the Codeigniter community in the new version. AS you know Codeigniter 4 is compatible with php version above 7. so it is utilizing the namespace feature of it abundantly in its new version.

Codeigniter 4

You can define your custom namespaces in app/Config/Autoload.php

If you open that particular file,you can see a array called $psr4. You have to add your namespaces there.

For eg:-

$psr4 = [
'App'         => APPPATH,              
APP_NAMESPACE => APPPATH,             
'Config'      => APPPATH . 'Config',
'IonAuth' => ROOTPATH . 'ion-auth-4',
                       'Admin'   => ROOTPATH . 'ci4-admin',
                       'Myapp'   => ROOTPATH . 'app',
];

You can see in the above configuration, i have defined some namespaces like Ion-Auth, Admin,Myapp .etc. What I am doing is assigning the path of those modules to that name. So I can access the controller,models,views in those folders just by using those static names.

For eg:- If am writing below line in any of my controller:-

echo view('Admin\Views\admin_template\admin_mainheader', $data);

System will identify Admin\ as a namespace and it will replace it with the path defined in namespace. so whatever included in that path will be executed. This gives a large advantage when we design our application.


4) DEFINING CONTROLLERS & MODELS

Codeigniter-3

In Codeigniter 3, we used to define controllers like:-

class Cms extends extends CI_Controller {

}

Controller class was extending CI_Controller Class.

we used to define models like:-

class Cms_model extends CI_model {

}

Model class was extending CI_model.

Codeigniter-4

In CI-4 this scenario is completely different.

In controller we have to define like:-

<?php

namespace App\Controllers;
use CodeIgniter\Controller;
use App\Models\Modelname;

class Cms extends Controller {

}

?>

Here we have to include Controllers in the top as namespaces. Also have to include models by defining it like this Use App/Models/Modelname. This place you can make use of the custom namespaces we saw above to include your models.

<?php
namespace App\Models;
use CodeIgniter\Model;

class CmsModel extends Model {
}
?>

Same like controllers, we have to define namespace paths for the models and include them. Here model is going to extend the model class instead of CI_model.

5) LOADING LIBRARIES,HELPERS.etc.

Codeigniter-3

        $this->load->database();       
        $this->load->library(['ion_auth', 'form_validation','pagination']);
        $this->load->helper(['url', 'language','form']);
In the previous version, we were loading database, library, helpers and models like this. Just check below how in the CI-4 version, everything is loading.

Codeigniter-4

     $db = \Config\Database::connect();
    $this->ionAuth    = new \IonAuth\Libraries\IonAuth();
    $this->validation = \Config\Services::validation();
    helper(['form', 'url','string','text']);
    $this->session       = \Config\Services::session();
    $pager = \Config\Services::pager();

Here Everything is loading differently. Just check the differences in both calling methods.

6)LOADING MODELS

Codeigniter-3

$this->load->model('cms_model');
$totalrecords= $this->cms_model->get_allrecord();

this is how model was loading and calling functions in the CI-3 Version. Loading the particular model by calling $this->load(->model() function. then calling particular function defined using $this->modelname function() . Now we will check how this is acheived in Codeigniter-4.

Codeigniter-4

Here we have to first include  path to the Model in top of controller before calling it..

use App\Models\CmsModel;

then to create object for the model. we have to declare like this-

$cmsmodel = new CmsModel();

then for calling the function:-

$totalrecords= $cmsmodel->get_allrecords();

Here you can see we are calling the function by using the object declared above. 


7) GET & POST VARIABLES ACCESSING

Codeigniter-3

Accessing Post variable from form submission
$keyword=   $this->input->post('keyword');
Accessing GET variables
$keyword=   $this->input->get('keyword');

Codeigniter-4

Accessing POST variables
$keyword= $this->request->getPost('keyword');
Accessing GET Variables
$keyword=$this->request->getVar('keyword');

8) FORM VALIDATION RULE SET

Codeigniter-3

  $this->form_validation->set_rules('txtMenuTitle', 'Title', 'trim|required');
  $this->form_validation->set_rules('txtParent', 'Parent', 'trim|required');

Codeigniter-4

  $this->validation->setRule('txtMenuTitle', 'Title', 'trim|required');
  $this->validation->setRule('txtParent', 'Parent', 'trim|required');

If you clearly notice you can see there are some minor changes only. form_validation chnaged to validation and set_rules changed to setRule.


9)PAGINATION

Codeigniter-3
    $searchstring='&keyword='.$keyword;
    $config['base_url'] = $data['urls'].'/auth/cms/list';
    $config['suffix']=$searchstring; // passing the search strings
    $config['total_rows'] = $data['count'];// total count of records fetched
    $config['per_page'] = $per_page_records; //count wanted per page
    $config["uri_segment"] = 2;         
    $config['first_url'] = $config['base_url'] .'?'. $config['suffix'];     
    $config['full_tag_open'] = "<ul class='pagination pull-right no-margin'>";
    $config['full_tag_close'] = '</ul>';
    $config['num_tag_open'] = '<li>';
    $config['num_tag_close'] = '</li>';
    $config['cur_tag_open'] = '<li class="active"><a href="#">';
    $config['cur_tag_close'] = '</a></li>';
    $config['prev_tag_open'] = '<li>';
    $config['prev_tag_close'] = '</li>';
    $config['first_tag_open'] = '<li>';
    $config['first_tag_close'] = '</li>';
    $config['last_tag_open'] = '<li>';
    $config['last_tag_close'] = '</li>';
    $config['prev_link'] = '<i class="ace-icon fa fa-angle-double-left"></i>';
    $config['prev_tag_open'] = '<li class="prev">';
    $config['prev_tag_close'] = '</li>';
    $config['next_link'] = '<i class="ace-icon fa fa-angle-double-right"></i>';
    $config['next_tag_open'] = '<li class="next">';
    $config['next_tag_close'] = '</li>';
    $config['use_page_numbers'] = FALSE;
    $config['enable_query_strings'] = TRUE;
    $config['page_query_string'] = TRUE;
    $config['reuse_query_string'] = FALSE;
    $config['attributes'] = array('keyword' =>$keyword);
    $config['attributes']['rel'] = TRUE;

    $this->pagination->initialize($config);// initializing the configs 
    $data['pagelinks']= $this->pagination->create_links();//creating links

Here it was like setting all your configuration into the config variable and then passing it to the initialize function, then the pagination class will be auto creating links for you which you will call in the view. Also please note that you can pass the search variables through suffix variable in the config.

Codeigniter-4

 if($keyword!=''){
         $cmsmodel->like('title',$keyword);
         $cmsmodel->orlike('page_title',$keyword);
       }
       
        $data['records']=$cmsmodel->paginate($per_page_records);
        $data['pager']=$cmsmodel->pager;

Here they removed the $config settings procedure. here we just have to call the paginate method on the particular model. Search parameters you can pass just like data fetching way. If you have more search parameters, you just have to append it in the $model->where() or $model->like type of functions. Now in the view you just have to call like:-

<?php  echo $pager->links(); ?>

This will display all the pagination links in the view page. You can further customize these links or pagination style using advanced ci-4 functions codeigniter is providing. Just refer their documentation for more details.

10) CALLING MODEL FUNCTIONS IN VIEWS

Codeigniter-3

<?php
$ci =&get_instance();
$ci->load->model('cms_model');
$record=  $ci->cms_model->getdetails($id);
?>

Sometimes we will be having requirement to call a particular Model function inside view itself. In those scenarios we can call that method in the view using instance function as described above

Codeigniter-4

In CI-4, its is more simple we have to just create an object in the controller method and just pass the object to the view. From there, we can call that particular method from model using the object.

So In Controller define like:-
<?php
 $cmsmodel = new CmsModel();
$data['cmsmodel']=$cmsmodel;
?>
Pass it to the view. then in View, just call the function.
<?php
  $record=  $cmsmodel->getdetails($id); 
?>

11) LOADING VIEWS IN THE CONTROLLER FUNCTIONS

Codeigniter-3

$this->load->view('cms/list', $data);

Just we have to call the view page by using $this-.load->view method.

Codeigniter-4

echo view('cms\admin_list', $data);

In CI-4 , it is more simplified and we have to just pass view file path to view() function.
For view file lying in other folders outside the app folder. You should define namespaces for them and call them like:-

echo view('Admin\Views\admin_template\admin_mainheader', $data);

12) CONFIGURING MODELS

Codeigniter-3

<?php
class Cms_model extends CI_model {
 
 protected $table = 'cms_pages';

        public function __construct()
        {
                $this->load->database();
        }

      public function functionname()
     {

     }
}
?>
Defining models by extending CI_Model class. Then defining $table in the proteted variable, so can us it all the functions coming under the model. In construct method, loading the database. Then defining each and every functions under it. This is how we did in CI-3.

Codeigniter-4

<?php
namespace App\Models;
use CodeIgniter\Model;

class CmsModel extends Model {
 
 protected $table = 'cms_pages';
 protected $primaryKey = 'page_id';
 protected $allowedFields = ['order','level','parent','position','published','default','featured','title','page_title','content','banner','date_update','seo_title','seo_keywords','seo_description','seo_slug'];

      
        public function get_records() {
 
    }

?>
Here in model, first you have to include namespace path. Then include codeigniter model file. Then define the Model extending Model class. Now here these 3 fields are almost mandatory to put. Sometimes codeigniter doesnt allow saving data without these variables defined in the model.

13) BASIC MODEL FUNCTIONS 

Codeigniter-3

-Insert

$this->db->insert($this->table, $data);

-Update

  $this->db->where('page_id', $id);
   $this->db->update($this->table,$data);

-Delete

  $this->db->where('page_id', $id);
  $this->db->delete($this->table);

-Retreive 
           $this->db->where('id',$id);
        $query = $this->db->get($this->table);
        return $query->result_array();

-Get Last Insert ID

$this->db->insert_id();

-Getting DB error Messages

$this->db->getErrorMessage();


Codeigniter-4


-Insert

$this->insert($data);

-Update

$this->update($id, $data);

-Delete

  $this->delete($id);

-Retreive 

$rec = $this->where(array('level' => '1'))->findAll();

-Get Last Insert ID

$this->insertID();

-Getting DB error Messages

$this->error();

If you watch closely you can see all function calling have been simplified a lot.