Search code examples
phpcomposer-phpautoloadpsr-4

PSR4 Composer Autoload Fatal error: Trait not found


I'm attempting to implement this error handling class into my php website https://github.com/niteshapte/advanced-error-exception-handler-logger-php but I keep getting the error

PHP Fatal error: Trait 'SingletonTrait' not found in www.example.com/application/core/ErrorExceptionHandler.php on line 37.

Line 37 is the second use SingletonTrait; statement.

I've only just wrapped my head around namespaces and then traits come along!

My code is below....I've stripped a lot of the code for brevity, but the full code can be viewed at the github URL above.

Can you spot what I'm doing wrong?

Source for www.example.com/application/core/ErrorExceptionHandler.php

<?php
namespace Utilities;
use SingletonTrait;

if(!defined('DIRECT_ACCESS')) {
    die("Direct access is forbidden.");
}

class ErrorExceptionHandler implements IUtilities {

    // Singleton instance - the line below generates the error
    use SingletonTrait;
....
}

Source for www.example.com/application/core/SingletonTrait.php

<?php
namespace Utilities;
use FrameworkException;

if(!defined('DIRECT_ACCESS')) {
    die("Direct access is forbidden.");
}

trait SingletonTrait {
.....
}

Source for www.example.com/application/core/FrameworkException.php

<?php
namespace Utilities;

if(!defined('DIRECT_ACCESS')) {
    die("Direct access is forbidden.");
}

class FrameworkException extends \Exception { }

Source for www.example.com/application/core/IUtilities.php

<?php
namespace Utilities;

if(!defined('DIRECT_ACCESS')) {
    die("Direct access is forbidden.");
}

interface IUtilities { }

Source for www.example.com/index.php

<?php
require '../vendor/autoload.php';

use Utilities\ErrorExceptionHandler;
define("DIRECT_ACCESS", TRUE);
ErrorExceptionHandler::getInstance();

This is what I have in my www.example.com/composer.json

"autoload": {
    "psr-4": { "": ["application/core/", "application/model/"],
               "Utilities\\": "application/core/",
               "SingletonTrait\\": "application/core/",
               "FrameworkException\\": "application/core/"
    }
}

Once I've uploaded that to my server, I issue composer dump-autoload at my PuTTY command line.

This generates the following source at www.example.com/vendor/composer/autoload_psr4.php

<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-docblock/src'),
    'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
    'Utilities\\' => array($baseDir . '/application/core'),
    'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
    'SingletonTrait\\' => array($baseDir . '/application/core'),
    'Gregwar\\Captcha\\' => array($vendorDir . '/gregwar/captcha'),
    'FrameworkException\\' => array($baseDir . '/application/core'),
    'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
    'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
    '' => array($baseDir . '/application/core', $baseDir . '/application/model'),
);

I've read as much as I can about autoloading traits but I haven't found an answer.

My command line PHP version is 5.6.30.


Solution

  • Remove the initial use SingletonTrait declaration inside ErrorExceptionHandler.php and it will work for you.

    Traits don't really make sense to be declared with the use statement outside of a class definition. There is a comment about this on the official PHP docs for traits that you can see below and read directly here:

    Note that the "use" operator for traits (inside a class) and the "use" operator for namespaces (outside the class) resolve names differently. "use" for namespaces always sees its arguments as absolute (starting at the global namespace)