Welcome Guest, Not a member yet? Register   Sign In
how to use controllers filters on CI4
#1

Hye,

Please, is somebody can explain me with details how to use controllers filters on CI4. With documentation i don't understand how to do ? i understand is necessary to create a class who implements FilterInterface. And after, what i need to do with my controller named for example Ctrl.php ?
If you can give a complete example, it would be very nice.

- if i create a controller in directory controller and if i want to modify the request or the response before or after entering in this controller, how can i do this.
Example : i sent datas from form and before entering on my controller, i would like to check if it's for example the good user who can access to this controller or if his session is ok, etc.

What should I create and where should I place my classes in the architecture with their methods ?

Thank you for your help.
Reply
#2

Filters are simply classes that implement FilterInterface, as you said. They have very few jobs. For before filters, they can modify the Request on the way in or, return a Response, like with a redirect() call. After filters can modify the Response before it's sent to the client, and will likely be used significantly less than before filters.

Due to the beauty of namespaces, the files themselves can live anywhere you want them to. An easy solution, and the one that the built in filters use, is to place the file at application/Filters/{your_file}.php. The class would then be in the App\Filters namespace. So, a simple access check like you're talking about might be something like this:

Code:
// File: application/Filters/Auth.php
<?php namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

class AuthFilter implements FilterInterface
{
   public function before(RequestInterface $request)
   {
       $auth = service('auth');

       if (! $auth->isLoggedIn())
       {
           return redirect('login');
       }
   }
   
   public function after(RequestInterface $request, ResponseInterface $response)
   {
       
   }  
   
}

What this does is it uses a custom Auth service which simply loads up an Auth class. It then checks if the user is logged in. If they are then nothing happens. The next filter is ran, or the controller is fired up. If, however, they're not logged in, then it returns a redirect response and script execution stops right there, the user is redirected and asked to log in. In the before/after methods you can put any logic you need to check. They should usually be fairly small, simple classes like this that can come up with a yes/no answer.

Your controllers don't know about filters, and don't care. If you've modified the Request object, then they'll get that. Otherwise, they are completely ignorant. Once you've created the class, you just need to configure it in application/Config/Filters.php. The docs will guide you through that. If you have specific questions about that process, feel free to ask.

This example, by the way, was ripped directly from the user guide. Make sure to read that page over a few times, and look at the existing ones.
Reply
#3

(This post was last modified: 01-12-2017, 09:44 AM by casa.)

Hye
Thanks you for your explaination, but i have always the same problem.
I don't understand Sad

# _________________
# I created this file on :

// application/Filters/AuthFilter.php
PHP Code:
namespace App\Filters;
use 
CodeIgniter\Config\Services;
use 
CodeIgniter\Filters\FilterInterface;
use 
CodeIgniter\HTTP\RequestInterface;
use 
CodeIgniter\HTTP\ResponseInterface;

class 
AuthFilter implements FilterInterface {

 
   public function before(RequestInterface $request) {
 
       // appel du service 'auth'
 
       $auth = \Config\Services::authentif();   //service('authentif') doesn't work in my code :(... i don't know why :(
 
       if ($auth->isLoggedIn() === true) {
 
          echo 'hello';
 
       } else {
 
           echo 'nothing';
 
       }
 
   }

 
   public function after(RequestInterface $requestResponseInterface $response) {
 
   }


#____________________
# Then, i created the file on application/Libraries/AuthLibrary.php
PHP Code:
namespace App\Libraries;
class 
AuthLibrary
{
 
   private $session;
 
   public function __construct(){
 
      $this->session = \Config\Services::session(); 
// for information, i config App.php for session storage in files (WRITEPATH.'sessions_cache', with directory named "sessions_cache" and no problem at this level
 
   }

 
   public function isLoggedIn(){
 
       return ($this->session->get('key')!== null)?TRUE:FALSE;
 
   }


#_____________________________
# Then, on application/Config/Services.php, i created this function :
PHP Code:
public static function authentif($getShared=false){
 
       if($getShared){
 
           return self::getSharedInstance('authlibrary');
 
       }
 
       return new \App\Libraries\AuthLibrary();
 
   

#_______________
# i created controller on application/Controllers/Test/Essai.php who extends Controller and i add directory Test as you can see. The code of Essai.php is :
PHP Code:
use CodeIgniter\Controller;

class 
Essai extends Controller
{
 
   private $session;

 
   public function __construct(...$params)
 
   {
 
       parent::__construct(...$params);
 
       session()->start();
 
   }
 
   
    public 
function index(){
 
       $this->session = \Config\Services::session();
 
       $this->session->set('key','12345');
 
       return view('essai_view');
 
   }


#______________________
# my essai_view.php file
PHP Code:
$session = \Config\Services::session();
echo 
'<br/><br/>var de session = '.($session->get('key')!==null?$session->get('key'):'aucune valeur').'<br/>'

#__________________________________
# Then on application/Config/Filters.php, i have many problems. I put !!! before my questions below.
PHP Code:
namespace Config;

use 
CodeIgniter\Config\BaseConfig;

class 
Filters extends BaseConfig
{
 
// Makes reading things below nicer,
 // and simpler to change out script that's used.
 
public $aliases = [
 
'csrf'  => \App\Filters\CSRF::class,
 
'toolbar' => \App\Filters\DebugToolbar::class,

 
// config of my filter
 
'authentification' => \App\Filters\AuthFilter::class,
 
 ];

 
// Always applied before every request
 
public $globals = [
 
'before' => [
 
// 'csrf'
     
'authentification'                  // if i understand before every request "authentification" is called.
  
],
 
'after'  => [
 
'toolbar'
 
]
 ];

 
// Works on all of a particular HTTP method
 // (GET, POST, etc) as BEFORE filters only
 //     like: 'post' => ['CSRF', 'throttle'],
 
public $methods = [];   // here for only method http                      

 // List filter aliases and any before/after uri patterns
 // that they should run on, like:
 //    'isLoggedIn' => ['before' => ['account/*', 'profiles/*']],
 
public $filters = [
 
    /* to make simple :
         'nameOfAliasFilter' => ['before' => [list of controllers or directory controller (ex: admin/* for all controllers in application/Controllers/Admin/) ]]  
     */

 
];


#_____________________________________________________
# With application/Config/Filters.php like above, i have this result when i call my controller "essai" :
PHP Code:
nothing

var de session 12345

// i thought that i should have "hello" and after "var de session = 12345". 
#_____
Thanks of your help. Sorry for my english, i am french.
Reply
#4

The first thing that catches my eye is that your Service you made won't work because you use a different name in the cached part ( authlibrary) than the method is named. It should be:

Code:
public static function authentif($getShared=false){
        if($getShared){
            return self::getSharedInstance('authentif');
        }
        return new \App\Libraries\AuthLibrary();
    }

That explains why your authentif function wasn't working.

With a quick look over the rest I think it's probably fine. However, don't expect echoing anything out of the filter to do anything. It would get lost in the shuffle I imagine. The only thing filters pay attention to is what is returned from the filter. In this case, you're returning nothing. Primarily it looks for either the Request or Response object to be returned from the filter. That's pretty much it. You could probably issue a die() statement and have that work but I can't recall off the top of my head. To make your method work, you would do something like this:

Code:
public function before(RequestInterface $request)
{
    $auth = \Config\Services::authentif();

    if ($auth->isLoggedIn() === false)
    {
       return redirect('login');
    }
}

This way, if the user is not logged in, it returns the Response object (through the redirect() function) which causes an immediate redirect. If they are logged in, then you don't need to do anything.

Does that help?
Reply
#5

Hello.
# thanks for all Smile
# Service corrected and it works
# I understand how to use Config/Filters.php

# For redirect, i'm using a lamp server i.e easyphp and i made an alias of my website and the directory is on another location of easyphp www directory. Thus, call "redirect('ctrl/fct')" create an error. I try "redirect('/')" and i see that it redirects me on www directory of my easyphp server. Does a mean to correct "redirect" or perhaps i write it bad.
With "header()" function i can redirect if necessary, but perhaps a means exists to use "redirect" in my case.
Reply
#6

Thank you for Filters! It's good decision!
Reply




Theme © iAndrew 2016 - Forum software by © MyBB