Alex Pliutau
Alex Pliutau

Reputation: 21957

Autoload custom library in Zend Framework 2.0

I need to use autoloading for my custom classes in Zend Framework 2.0. My custom library located in /vendor/Garvey/library/Garvey. I have a simple extended AbstractTable class in /vendor/Garvey/library/Garvey/Db/Table/AbstractTable.php:

<?php

namespace Garvey\Db\Table;

use Zend\Db\Table\AbstractTable;

abstract class AbstractTable extends AbstractTable
{
    public function getItemById($id)
    {

    }
}

In the index.php I have the following code:

require_once 'vendor/ZendFramework/library/Zend/Loader/AutoloaderFactory.php';
Zend\Loader\AutoloaderFactory::factory(array('Zend\Loader\StandardAutoloader' => array(
    'prefixes' => array(
        'Garvey' => 'vendor/Garvey/library/Garvey',
    )
)));

But I have the following error. What I have missed?

Fatal error: Class 'Garvey\Db\Table\AbstractTable' not found

Thank you in advance.

Upvotes: 9

Views: 20415

Answers (5)

Kdecom
Kdecom

Reputation: 728

Have a quick look at this post.

Now next step is add some code into our custom library.

First of all open a file ./vendor/Garvey/autoload_classmap.php

return array(

    'Garvey\Module' => __DIR__ . '/Module.php',

    'Garvey\Db\Table' => __DIR__ . '/library/Garvey/Db/Table/AbstractTable.php',

)

Next is ./vendor/Garvey/Module.php

namespace Garvey;

use Zend\ModuleManager\Feature\AutoloaderProviderInterface;

class Module implements AutoloaderProviderInterface
{
    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\ClassMapAutoloader' => array(
                __DIR__ . '/autoload_classmap.php',
            ),

            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/library/' . __NAMESPACE__,
                ),
            ),
        );
    }
}

Now inside your library create a file inside a folder:

./vendor/Kdecom/library/Kdecom/Db/Table/AbstractTable.php

One final thing that we need to do which is add this library into your application.config.php file.

So your application.config.php file will looks something like this way...

return array(
    'modules' => array(
        'Application',
        'Garvey'
    ),

    'module_listener_options' => array(
        'config_glob_paths'    => array(
            'config/autoload/{,*.}{global,local}.php',
        ),

        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
);

Upvotes: 2

dan_nl
dan_nl

Reputation: 4446

Matthew Weier O'Phinney explains in this video that there are now 3 methods for autoloading :

  • ZF1-style include_path autoloader ( old zf1 method, not recommended )
  • Per-namespace/prefix autoloading ( new zf2 method, better )
  • Class-map autoloading ( recommended and the fastest )

A class-map generator utility is mentioned in the docs that will take care of writing the /vendor/vendor_name/library/autoload_classmap.php for you.

The solution you found is similar to the one Matthew mentions in the video for the Per-namespace/prefix autoloading. Following the code structure in ZendSkeletonApplication, that code would go in the /init_autoloader.php file, rather than in the /public/index.php file.

Upvotes: 3

Sergey Romanov
Sergey Romanov

Reputation: 3080

Or you can defime method in Module.php

public function getAutoloaderConfig()
{
    $return = array(
        'Zend\Loader\ClassMapAutoloader' => array(
            __DIR__ . '/autoload_classmap.php'
        ), 
        'Zend\Loader\StandardAutoloader' => array(
            'namespaces' => array(
                __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                'Garvey' => __DIR__ . '/../../vendor/Garvey/library/Garvey',
            )
        )
    );
}

But I would not recommend it. Since ZF2 purpose all centered about speed in autoloading the best way is to use class_map style to load your classes. It will work much quicker at the end but require additional work. You can to register every class in you class_map file.

You can create class_map.php in the root of your library and place there

<?php
return array(
    'Garvey\Db\Table\AbstractTable' => __DIR__ . '/Garvey/Db/Table/AbstractTable.php', 
);

And add there as many classes as you use. And in getAutoloaderConfig() you can add you classmap

public function getAutoloaderConfig()
{
    $return = array(
        'Zend\Loader\ClassMapAutoloader' => array(
            __DIR__ . '/autoload_classmap.php',
            __DIR__ . '/../../vendor/Garvey/library/Garvey/class_map.php',
        ), 
        'Zend\Loader\StandardAutoloader' => array(
            'namespaces' => array(
                __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
            )
        )
    );
}

Upvotes: 11

atti
atti

Reputation: 135

Your original index.php would also worked if you changed the 'prefixes' key to 'namespaces' and specify path like below:

Zend\Loader\AutoloaderFactory::factory(array('Zend\Loader\StandardAutoloader' => array(
    'namespaces' => array(
        'Garvey' => dirname(__DIR__) . '/vendor/Garvey',
    )
)));

Upvotes: 12

Alex Pliutau
Alex Pliutau

Reputation: 21957

I have found the answer. Put this in your index.php:

require_once 'vendor/ZendFramework/library/Zend/Loader/StandardAutoloader.php';
$loader = new Zend\Loader\StandardAutoloader();
$loader->registerNamespace('Garvey', realpath('vendor/Garvey/library/Garvey'));
$loader->register();

Upvotes: 2

Related Questions