Roberson Young
Roberson Young

Reputation: 31

zend framework2 how does the autoload function work

recently I was learning zend framework 2, and there's a problem annoying me for a long time, things look like this:

<?php
namespace Album\Model;

// Add these import statements
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;

class Album implements InputFilterAwareInterface
{
    public $id;
    public $artist;
    public $title;
    protected $inputFilter;

    public function exchangeArray($data)
    {
        $this->id     = (isset($data['id']))     ? $data['id']     : null;
        $this->artist = (isset($data['artist'])) ? $data['artist'] : null;
        $this->title  = (isset($data['title']))  ? $data['title']  : null;
    }

    // Add content to these methods:
    public function setInputFilter(InputFilterInterface $inputFilter)
    {
        throw new \Exception("Not used");
    }

    //....
    ?>

This code was a section of the "skeleton application" programme, which was a tutorial of ZF2. The first time I see the programme, I don't understand what's the usage of "namespace" and "use", because this two keyword doesn't exist in php5.2(also the same in the earlier edition), so I go to see the manual and try to understand it.I write a programme to simulate what really happens:

<?php
use script\lib\test;

$o = new test();
echo $o->getWelcome();

function __autoload( $className ) {  
$classname = strtolower( $classname );  
require_once( dirname( __FILE__ ) . '/' . $classname . '.php' );  
}
?>

the programme above works well, of course I created two folders named script and lib, and there's a file named test.php. Seems like every thing is clear, zend framework also has a autoload function, BUT when I noticed the codes in "skeleton application programme", there was a namespace in the beginning, so I adds the namespace to my programme too:

<?php
namespace test;
use script\lib\test;

$o = new test();
echo $o->getWelcome();

function __autoload( $className ) {  
$classname = strtolower( $classname );  
require_once( dirname( __FILE__ ) . '/' . $classname . '.php' );  
}
?>

the page returned me inforamtion as following: Fatal error: Class 'script\lib\test' not found in E:\wamp\www\test\test_29.php on line 6

I tried to change the namespace's name such as script\lib, script\lib\test... but it's useless.

Any answer will be appreciated, thanks.


Now I will give you more details about this issue: To understand the usage of "namespace" and "use", I looked over the materials on php.net: http://php.net/manual/en/language.namespaces.importing.php In this page, there was a section of code looks like this:

Example #1 importing/aliasing with the use operator

<?php
namespace foo;
use My\Full\Classname as Another;

// this is the same as use My\Full\NSname as NSname
use My\Full\NSname;

// importing a global class
use ArrayObject;

$obj = new namespace\Another; // instantiates object of class foo\Another
$obj = new Another; // instantiates object of class My\Full\Classname
NSname\subns\func(); // calls function My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); // instantiates object of class ArrayObject
// without the "use ArrayObject" we would instantiate an object of class
?>

Now let's review the programme I write in the above:

<?php
namespace test;
use script\lib\test;

$o = new test();
echo $o->getWelcome();

function __autoload( $className ) {  
$classname = strtolower( $classname );  
require_once( dirname( __FILE__ ) . '/' . $classname . '.php' );  
}
?>

It's the same, I'm trying to simulate that instance, if we don't use the autoload function:

<?php
namespace test;
use script\lib\test;
require_once 'script/lib/test.php';

$o = new test();
echo $o->getWelcome();
?>

It works well too, BUT when I use __autoload function to load the class file, there's something wrong. I don't konw where's problem, OR any body tried to write an instance to put the "Example #1" into practice? I will wait for your answer.

Upvotes: 2

Views: 389

Answers (2)

Machavity
Machavity

Reputation: 31614

I think you're misunderstanding what's going on here.

Namespaces allow you to, more or less, create "directories" for your classes. So you can create the \Foo class and the \Test\Foo class (where \ represents the "root" of your application). The way autoloading works is that your files mirror your namespacing. So foo.php would be in the root of your autoloading but you would create /test/foo.php for \Test\Foo The use keyword has two uses. One is to alias class files and the other is, in PHP 5.4 or later, to bring in a Trait into your current class.

Now, to your question. First, Let's look at your code

<?php
namespace test;
use script\lib\test;

$o = new test();
echo $o->getWelcome();

This is confusing. You declare a namespace (which you don't need to do here) but then you alias it to script\lib\test. PHP is now looking for a file called /script/lib/test.php, which your error message says doesn't exist. But you said the file does exist so let's look at that

public function getWelcome() {
     return 'welcome';
}

This isn't a class. It's a function. For this example you need a complete class

<?php
namespace script\lib;
class test {
    public function getWelcome() {
        return 'welcome';
    }
}

Lastly, let's talk autoloading. You don't need to use use with autoloading. Your autoloader should take care of that for you. You should, however, use spl_autoload_register(), as __autoload() is soon to be depreciated.

Upvotes: 4

bitWorking
bitWorking

Reputation: 12655

From ZF2 docu

Zend\Loader\StandardAutoloader is designed as a PSR-0-compliant autoloader. It assumes a 1:1 mapping of the namespace+classname to the filesystem, wherein namespace separators and underscores are translated to directory separators.

Read more about: PSR-0

So if you're using namespaces the classname that gets send to the autoloader doesn't look like test. It looks like YOUR_NAMESPACE\test. YOUR_NAMESPACE is the namespace that you defined in the class with namespace YOUR_NAMESPACE;

PSR-0 is a standard that says: Your namespace should reflect your filesystem. You only have to replace the backslashes with forward slashes. Or _ with / if you're using pseudo namespaces like in ZF1. (Album_Model_Album)

So output the $className that is sent to your autoloader and you will see..

Upvotes: 1

Related Questions