1
\$\begingroup\$

I wanted to write a simple Log class for PHP, I use ajax calls with AngularJS and often return the log in an array

Example:

$return['data'] = $returnedDataArray;
$return['log'] = $logDataArray;
$return['status'] = 'success';
echo json_encode($return);

I was hoping to implement a logging system in my other classes, like my DB wrapper, etc.

Example:

Log::put('sql', $sql, 'DB');
Log::put('fields', $fieldsArray, 'DB');

And than pass the log.

Example:

$return['log'] = Log::getLog();

Here is my Log class:

class Log {
    private static $_loggingOn = true, $_log = array();

    public static function put ($key, $value, $className = null, $functionName = null) {
        if ($className) {
            if ($functionName) {
                self::$_log[$className][$functionName][$key] = $value;
            } else {
                self::$_log[$className][$key] = $value;
            }
        } else {
            self::$_log[$key] = $value;
        }
    }

    public static function getLog () {
        if (self::loggingOn()) {
            return self::$_log;
        }
        return array('Logging is turned off.');
    }

    public static function loggingOn () {
        return self::$_loggingOn;
    }
}

I am wondering if using the static class would be a recommended approach?

\$\endgroup\$
1
  • \$\begingroup\$ What exactly are you logging in this class? It's not writing anything to anywhere... besides: you've not included the possibility of having to log in a namespaced environment, and you're using static, which isn't very useful in a PHP context \$\endgroup\$ Commented Jan 4, 2014 at 18:41

1 Answer 1

3
\$\begingroup\$

No, using static methods is not a recommand approach. With static methods, your class always knows which class it calls. That means you can never switch to another logger class (e.g. one that writes the logs in a file).

A class should be independent of other classes as much as possible. In this case, you should just create a LoggerInterface (or use the one from PSR-3) and base on that interface. Inject it in the classes that needs a logger and then use that object. This way, you can always change from loggers (as long as they implement the correct interface) and your class doesn't know which classes it uses.

Example:

interface LoggerInterface
{
    public function put($key, $value, $class = null, $function = null);
    public function getMessages();
}

class Logger
{
    protected $messages;

    public function put($key, $value, $class = null, $function = null)
    {
        // ...
    }

    public function getMessages()
    {
        // ...
    }
}

class DataBase
{
    protected $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function someDbFunction(...)
    {
        // ... do something

        $this->logger->put(...); // log something
    }
}

This approach is called Dependency Injection. To make live easier for you, you can sue a Dependency Injection Container (also called a Service Container) to manage which classes depends on which other classes and creating those objects. A simple example is Pimple


There are also more disadvantages of using static methods. You can for instance never have 2 different instances of the logger, as there are no instances. That means that all messages are put in the same instance. You may want to internally use a logger in the Database section of your lib and another logger in the Form section of your lib and then one logger for your complete lib.

\$\endgroup\$
1
  • \$\begingroup\$ With static methods, your class always knows which class it calls. That means you can never switch to another logger class That's not entirely true. If you called the class as static::put() instead of self::put() then you can override it with late static binding. \$\endgroup\$
    – MrLore
    Commented Jul 14, 2014 at 11:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.