Search code examples
phpclassloggingglobal-variableslog4php

Allow instantiated class to access class include in creator


I have my main PHP file which is run whenever someone hits my server. It looks something like this:

<?php

$config = require_once('./config/general.php');

define('ROOT', __DIR__.'/');

include(constant('ROOT').'libraries/log4php/Logger.php');
Logger::configure(constant('ROOT').'config/logging.xml');
$log = Logger::getLogger('main');

$requested_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$route_url = str_replace($config['baseURL'], '', $requested_link);
$route_url = $route_url == '' ? '/' : $route_url;

define('ROUTE', $route_url);

require_once 'routeme.php';

routeme.php finds the best "routing" class to handle the requested url. It instantiates that class then passes the request info to the instance of the router class it created for it to be handled.

All the routers extend a base class:

<?php
namespace Blaze;
class Router {
    private $log;

    public function __construct() {

        // The __CLASS__ constant holds the class name
        $this->log = Logger::getLogger(__CLASS__);
    }

    public function routes (){
        return array();
    }
}

An example router:

<?php
namespace Blaze;
class GeneralRouter extends Router {

    public function RootRoute ($url){
        $log->info($url);
    }

    public function routes (){
        return array(
            '/' => 'RootRoute'
        );
    }
}

when I try to run the application, it fails because the Router class doesn't see the included Logger class from log4php (the log statements in the main file run fine, of course). I can't re-include the Logger class on a per-router basis because log4php only allows it's self to be included once in an application (probably to prevent file locking conflicts). How can I let the Router access/see the Logger class?

The solution has to be expandable, i.e I will have more classes later like the Router class that will also need to access the Logger class.


Solution

  • In your Router class, import the Logger class:

    <?php
    
    namespace Blaze;
    
    use Logger;
    
    class Router{
        public function __construct(){
            $this->log = Logger::getLogger(__CLASS__);
        }
    }
    

    If you don't import Logger, when you try to call it, PHP is trying to retrieve the Logger class in the same namespace:

    Blaze\Logger
    

    If you don't want to import it, you could do:

    $this->log = \Logger::getLogger(__CLASS__);
    

    Then in your GeneralRouter:

    public function RootRoute($url){
        $this->log->info($url);
    }