Class not found using namespace compilant PSR-4 on PHP

1.3k views Asked by At

I'm very confusing about namespace on php (>5.4.*) and composer

Scenario

|vendor
   |autoload.php
    |abkrim
       |cputils
          |src
             |CpPanelBackTest.php

Code CpPanelBackTest.php

namespace Abkrim\Cputils;
class CpPanelBackTest
{
    public static function getDate(){
      $year = date('Y');
      $month = date('m');
      $day = date('d');
      return $day . '/' . $month . '/' . $year;
    }
}

File test.php

require __DIR__.'/../../vendor/autoload.php';
use Abkrim\Cputils\CpPanelBackTest;
echo 'Date today is: ' . CpPanelBackTest::getDate();

File composer.json on vendor/abkrim/cputils

"autoload": {
   "psr-4": {
      "Abkrim\\Cputils\\": "src/"
   }
}

Get error ->

PHP Fatal error:  Class 'CpPanelBackTest' not found in at file xxxx line xxxx

If change code for CpPanelBackTest.php

//namespace Abkrim\Cputils; //coment namespace
class CpPanelBackTest
{
    public static function getDate(){
      $year = date('Y');
      $month = date('m');
      $day = date('d');
      return $day . '/' . $month . '/' . $year;
    }
}

And file test.php

//require __DIR__.'/../../vendor/autoload.php';
//use Abkrim\Cputils\CpPanelBackTest;
require_once __DIR__ . '/../../vendor/abkrim/cputils/src/CpPanelBackTest.php';

Now work fine.

I'm lost. I'm not understanding anything about it echo 'Date today is: ' . CpPanelBackTest::getDate();

1

There are 1 answers

2
Sven On

The error you are experiencing is triggered when PHP cannot load or find a class. The name in that error message is the fully qualified name of the class being searched.

That name in your error message does not contain a namespace. That means your usage was not being detected as using a namespace. Which is correct if you look at the one line: echo 'Date today is: ' . CpPanelBackTest::getDate(); No namespace here.

You do have a use statement before that, and it is supposed to import the class into the current (global) namespace. And I believe it would do that - my tests show that the code posted in your question would probably correctly work. The problem is: I find it difficult to create a whole test case with Composer, a separate package, including it and so on, so I did only run a tiny replacement test which does NOT take into account the differences of the file system.

<?php

namespace Foo {
class Bar {}
}

namespace {
use Foo\Bar;
var_dump(new Bar);
}

See it in action: http://3v4l.org/mrVsI

And this is my guess: PHP classes are NOT case sensitive, but the conversion from a class name into a path and file name IS case sensitive on some filesystems. If you mistyped only one letter in your code, Composer will be unable to detect the prefix and/or will be unable to locate the correct file.

Unfortunately you didn't do a correct test to prove that the autoloading is wrong. You should have only removed the autoloader, and instead require the file containing the class - without disabling the namespace.