CodeIgniter Forums

Full Version: How can I extend more than only MY_Controller with Composer?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hello,


I was trying to create two base Controllers depending on whether the user is logged in or not.

I already tried with Phil Sturgeon's solution https://philsturgeon.uk/blog/2010/02/Cod...ng-it-DRY/ and works without a problem (my tutorial on this is here: http://avenir.ro/codeigniter-tutorials/n...ase-class/). 

But I was wondering if there is a way to do this by using Composer.

So, at first I tried doing it with file based autoloading. I enabled composer autoloading inside config.php: $config['composer_autoload'] = TRUE;

I created a base controller named Admin_Controller.php:

PHP Code:
<?php
class Admin_Controller extends CI_Controller
{
 
   function __construct()
 
   {
 
       parent::__construct();
 
       echo 'This is from admin controller';
 
   }


After that, I created a composer.json inside application:

Code:
{
   "description" : "The CodeIgniter framework",
   "name" : "codeigniter/framework",
   "license": "MIT",
   "require": {
       "php": ">=5.2.4"
   },
   "autoload": {
       "files" : [
           "core/Admin_Controller.php"
       ]
   }
}

And after that I did an extend in the Welcome Controller

PHP Code:
<?php defined('BASEPATH') OR exit('No direct script access allowed');

class 
Welcome extends Admin_Controller {

public function 
index()
{
 
       $this->load->view('welcome_message');
}



...but it doesn't seem to work...

Now, if I instead extend CI_Controller and look at the loaded classes, I see that the Admin_Controller is loaded:

PHP Code:
<?php defined('BASEPATH') OR exit('No direct script access allowed');

class 
Welcome extends CI_Controller {

public function 
index()
{
 
       echo '<pre>';
 
       print_r(get_declared_classes());
 
       echo '</pre>';
 
       if(class_exists('Admin_Controller'))
 
       {
 
           echo 'It exists';
 
       }
 
       $this->load->view('welcome_message');
}


So, where did I did wrong? Could someone help me?
(12-08-2014, 08:02 AM)Avenirer Wrote: [ -> ]Hello,


I was trying to create two base Controllers depending on whether the user is logged in or not.

I already tried with Phil Sturgeon's solution https://philsturgeon.uk/blog/2010/02/Cod...ng-it-DRY/ and works without a problem (my tutorial on this is here: http://avenir.ro/codeigniter-tutorials/n...ase-class/). 

But I was wondering if there is a way to do this by using Composer.

So, at first I tried doing it with file based autoloading. I enabled composer autoloading inside config.php: $config['composer_autoload'] = TRUE;

I created a base controller named Admin_Controller.php:


PHP Code:
<?php
class Admin_Controller extends CI_Controller
{
 
   function __construct()
 
   {
 
       parent::__construct();
 
       echo 'This is from admin controller';
 
   }


After that, I created a composer.json inside application:


Code:
{
   "description" : "The CodeIgniter framework",
   "name" : "codeigniter/framework",
   "license": "MIT",
   "require": {
       "php": ">=5.2.4"
   },
   "autoload": {
       "files" : [
           "core/Admin_Controller.php"
       ]
   }
}

And after that I did an extend in the Welcome Controller


PHP Code:
<?php defined('BASEPATH') OR exit('No direct script access allowed');

class 
Welcome extends Admin_Controller {

public function 
index()
{
 
       $this->load->view('welcome_message');
}



...but it doesn't seem to work...

Now, if I instead extend CI_Controller and look at the loaded classes, I see that the Admin_Controller is loaded:


PHP Code:
<?php defined('BASEPATH') OR exit('No direct script access allowed');

class 
Welcome extends CI_Controller {

public function 
index()
{
 
       echo '<pre>';
 
       print_r(get_declared_classes());
 
       echo '</pre>';
 
       if(class_exists('Admin_Controller'))
 
       {
 
           echo 'It exists';
 
       }
 
       $this->load->view('welcome_message');
}


So, where did I did wrong? Could someone help me?

Try to move your Admin_Controller.php from core to library....
You could also try a spl_autoload_register in your config file like this:

PHP Code:
function app_lib($classname) {
 
   if strpos$classname'CI_' ) !== ) {
        
$file APPPATH 'libraries/' $classname '.php';
        if ( 
file_exists$file ) && is_file$file ) ) {
            @include_once 
$file;
        }
    }
}
spl_autoload_register('app_lib'); 
Please don't use my solution.... i see you already used Phil Sturgeon's solution.

I personally create a MY_Controller.php in the core directory and than Admin_Controller.php and Site_Controller.php in library directory.
An of course, the spl_autoload_register in config file...i never used the composer for autoloading classes.
just need to ask which config file you are putting this code config.php or any other file what if we put in index.php file.

(12-09-2014, 06:07 AM)Dracula Wrote: [ -> ]
PHP Code:
function app_lib($classname) {
 
   if strpos$classname'CI_' ) !== ) {
 
$file APPPATH 'libraries/' $classname '.php';
 if ( 
file_exists$file ) && is_file$file ) ) {
 @include_once 
$file;
 }
 }
}
spl_autoload_register('app_lib'); 
Here is our autoloader that goes in the config.php file at the very bottom.

PHP Code:
/*
| -------------------------------------------------------------------------
| Native spl_autoload_register() - by Kenneth Vogt
| -------------------------------------------------------------------------
|
| Here is an updated version of Phil Sturgeon’s code:
|
| Thanks to Phil Sturgeon Kenneth Vogt and InsiteFX.
|
| NOTE:
| Requires PHP 5.3.+
| As of CI 3.0 Dev - The constant EXT has been removed modified
| to use '.php' now instead of EXT.
| should work for all version of CI and PHP 5.3
|
| Place at the bottom of your ./application/config/config.php file.
| -------------------------------------------------------------------------
*/

spl_autoload_register(function($class)
{
    if (
strpos($class'CI_') !== 0)
    {
        if (
file_exists($file APPPATH 'core/' $class '.php'))
        {
            include 
$file;
        }
        elseif (
file_exists($file APPPATH 'libraries/' $class '.php'))
        {
            include 
$file;
        }
    }
}); 
(12-22-2014, 09:13 AM)ivantcholakov Wrote: [ -> ]See this post by Lonnie Ezell http://forum.codeigniter.com/thread-420-...ml#pid2665

Well... I did try that, but still no luck, that is why I tried to get back to the basics... with psr-0. And it didn't work Sad
(12-22-2014, 03:37 PM)Avenirer Wrote: [ -> ]
(12-22-2014, 09:13 AM)ivantcholakov Wrote: [ -> ]See this post by Lonnie Ezell http://forum.codeigniter.com/thread-420-...ml#pid2665

Well... I did try that, but still no luck, that is why I tried to get back to the basics... with psr-0. And it didn't work Sad

He only gives the clue without details. But he has published code that covers exatly the topic you are working on. Here are his base controllers https://github.com/ci-bonfire/Sprint/tre...ontrollers and here is his Composer.json https://github.com/ci-bonfire/Sprint/blo...poser.json
I have an update on the problem. It seems to me that the "composer_autoload" parameter in the config file is somehow broken (on first view). This is what I did now:

1. I created a parent directory where I put my base controllers inside application ('application/avenirer/BaseControllers').

2. In BaseControllers directory I create a file named Admin_Controller.php:

PHP Code:
<?php namespace Avenirer\BaseControllers;

class 
Admin_Controller extends \CI_Controller
{
 
   function __construct()
 
   {
 
       parent::__construct();
 
       echo 'This is from admin controller';
 
   }


3. I create a composer.json inside application (added a require php 5.4 for namespacing sake. is not really necessary for that line... Don't worry about namespacing, I tried with classmap too, and I have the same problem...):

Code:
{
   "require": {
       "php": ">=5.4"
   },
   "autoload": {
       "psr-4": {
           "Avenirer\\":"avenirer"
       }
   }
}

4. I do a "composer install" inside application so that the autoloaders are created. Now, if I look inside 'application/vendor/composer/autoload_psr4.php' I will see:

PHP Code:
return array(
 
   'Avenirer\\' => array($baseDir '/avenirer'),
); 

5. Next step would be to require_once the composer's autoloader. For explanation sake I will do that inside the application/config/config.php file, just below the composer_autoload config item (making sure that the parameter is set to FALSE):

PHP Code:
$config['composer_autoload'] = FALSE;
require_once 
APPPATH.'vendor/autoload.php'

6. Now I create a controller and do an extend for Admin_Controller:

PHP Code:
<?php defined('BASEPATH') OR exit('No direct script access allowed');

class 
Welcome extends Avenirer\BaseControllers\Admin_Controller {

 
   public function index()
 
   {
 
       echo '<pre>';
 
       print_r(get_declared_classes ());
 
       echo '<hr/><hr />';
 
       print_r(get_included_files ());
 
       echo '</pre>';
 
   }


7... And I get a 'hello' from my Admin_Controller.

Conclusion: it works.

Questions to be answered:

If instead, I set composer_autoload parameter to TRUE and comment the autoload.php I put earlier...:

PHP Code:
$config['composer_autoload'] = TRUE;
//require_once APPPATH.'vendor/autoload.php'; 

... it doesn't work  Huh

Now, to verify if the autoload.php was loaded, instead of extending Admin_Controller, I will extend CI_Controller. The print_r() function show me that the files were loaded corectly.

But when I extend Avenirer\BaseControllers\Admin_Controller I get the same Fatal error: Class 'Avenirer\BaseControllers\Admin_Controller' not found in...

What is wrong here?
So many different solutions.  I don't use any of them.

This is what I do.

in index.php:

Quote:/*

 * --------------------------------------------------------------------
 * COMPOSER AUTOLOAD
 * --------------------------------------------------------------------
 */
include_once './vendor/autoload.php';

Lets say I'm going to use rabbitmq.

In my rabbitmq function library:

Quote:<?php if (!defined('BASEPATH')) exit('No direct script access allowed');


use PhpAmqpLib\Connection\AMQPConnection;
use PhpAmqpLib\Message\AMQPMessage;

Done...   Cool 

In fact, I have multiple composer libraries that I use.  None of them are loaded into the Base Controller.  

All my composer libs are in code igniter libs that I have created.  So when I want to use a composer lib, I load up the CI lib, do what I need to do and that's it.

No messing with namespaces, no messing with the Base Controller.  Nice and easy....   Angel
Pages: 1 2