ZF2: autoloading libraries without namespaces - php

Previously I have only been using third party libraries that use namespaces together with Zend Framework 2. Now I need to use a library that does not use namespaces, and I cannot seem to make it work. I installed it via Composer, and it is installed fine into the vendor directory. I am trying to use it as follows:
$obj = new \SEOstats();
The result is a fatal error indicating that the class could not be found. I have tried to manually configure the StandardAutoloader, but so far without any luck. I thought that the autoloading would be done for me automatically when installing through Composer, but I guess that is not the case without namespaces? I haven't seen any reference to the library in the autoload files that Composer generated. I guess I have to do it manually - but how?
Thanks in advance.

You can use the files and classmap keys.
As an example consider this composer.json:
{
"require": {
"vendor-example/non-psr0-libraries": "dev-master",
},
"autoload":{
"files": ["vendor/vendor-example/non-psr0-libraries/Library01.php"]
}
}
Using the files key you can then use
$lib = new \Library01();
Use the classmap key when you need to load multiple files containing classes. The composer.json would be:
{
"require": {
"vendor-example/non-psr0-libraries": "dev-master",
},
"autoload":{
"classmap": ["vendor/vendor-example/non-psr0-libraries/"]
}
}
Composer will scan for .php and .inc files inside the specified directory configuring the autoloader for each file/class.
For more info you can check http://getcomposer.org/doc/04-schema.md#files and http://getcomposer.org/doc/04-schema.md#classmap
If you are under a namespace while creating the object, you must use the "\" (root namespace), otherwise you will use the Library01 class under the current namespace (if you have one, if you don't have one you'll get an error).

Related

Autoloading PHP file in composer package

I'm trying to create a composer package that also contains src/functions.php with some general functions. I have the following in composer.json to make it autoload:
"autoload": {
"files": ["src/functions.php"]
}
When I import this package into a project it will try to load src/functions.php in the current project (local) in stead of the imported package. Is there a way to ensure the correct file is loaded when imported (./vendor/bla/src/functions.php)?
Autoloading is not for loading everything. If src/functions.php contains class just ensure it's properly namespaced and I see no reason why autoloader would pick your local class instead of package's. If you are using the same namespace for the package and for code in your project then basically you should stop doing so.
If src/functions.php is just bunch of functions, then I strognly suggest refactoring the code and wrap them in properly namespaced class. You can make your functions static methods so basically not much would change from usage perspective.
EDIT
Once you finish refactoring, change your composer.json from what you shown in question to:
"autoload": {
"classmap": ["src/"]
}

Fatal error: Class 'CDbTestCase' not found

I'm new in php and I have to do the testing for an app. I'm trying to make unit testing but an error messages is displayed. I have many weeks ago and I cannot fix it, please help me!!
The message says: Fatal error: Class 'CDbTestCase' not found.
I read and follow many tutorials about this issue but it doesn't work.
I'm using Yii, Eclipse IDE and Composer.
I think the problem is in bootstrap.php but I don't use it because I'm working with composer, this is the composer.json
{
"require-dev": {
"yiisoft/yii": "1.1.*",
"phpunit/phpunit": "4.6.*",
"phpunit/phpunit-selenium": ">=1.2",
"codeception/codeception":"*",
"phpunit/dbunit": ">=1.2"
},
"autoload": {
"psr-0": {"": "vendor/autoload.php"},
"psr-4": {"": "/../framework/test/CDbTestCase.php"}
}
}
The bootstrap file is needed to load the yii framework. CDbTestCase is part of the yii framework so failing to include yii will give you this error if your tests depend on yii's unit test related classes.
Use the included bootstrap file and make sure you also include composer's autoload.php file. I normally add this to my yii config file (I believe by default, yii uses the test.php config file for custom testing related settings. You can include autoload.php inside this file)
Somewhere at the top of your yii config file
// Include composer autoload
require_once 'path/to/composer/vendor/autoload.php';
Your Composer autoloading is completely wrong.
Don't include the composer autoloader "vendor/autoload.php" in the autoloading of your own composer.json. There is only one autoloader, and it is created using your autoload data as well as any libraries.
The PSR-4 autoloading is also wrong. You have to state a directory where classes are put into files according to PSR-4. You point to one single file.
You don't use class prefixes for PSR-0 and PSR-4. This is bad for performance, because you are stating that ANY class could be in the directory. So Composer has to search for that class in this directory as well, even for classes that are guaranteed to not be there. Always use a prefix, and make it as long as possible to allow unique matches: One prefix should only ever point to exactly one directory structure.
You should explain why you don't use a bootstrap file in your tests. The minimal required bootstrap code for PHPUnit is to include the Composer autoloader. Additionally, you should add things that are required in your tests and have to be done once, like initialization of framework components -YMMV.

Adding namespace to imported third-party package in Composer

I am importing a third-party package into my project using composer.
The composer.json of the package autoloads its classes using "classmap":
{
...
"name"=>"vendor/project",
...
"require": {
"php": ">=5.2.0"
},
"type": "library",
"include-path":["src/"],
"classmap": [
"src/path/to/lib1",
"src/path/to/lib2"
]
...
}
My project composer.json pulls the package in using "require".
{
...
"require": {
"vendor/project": "m.n.*",
}
...
}
I'd like to add a namespace that can prefix all the classes of that package when I use it in my project, can I do this in composer?
I am aware I can use autoload at the level of my project, but presumably these classes don't need loading again and where do I point it?
You cannot add a namespace to a project without editing every individual file in the project and adding a namespace .. declaration at its top. This is likely infeasible.
If you namespace your own code, there should be no possible problem of a name clash.
If the library clashes with yet another non-namespaced third party library which you also cannot feasibly namespace, then you're in trouble. Unless this is the case, there's no real reason to worry about it.
If composer's definition is set up properly, all you should need to do is simply use the class:
$foo = new \VendorClass;
Composer's autoloading will take care of loading the class, a missing namespace is of no concern (see above).

Using Composer Packages with Slim PHP 2.0

I am trying to build a REST API using Slim PHP 2.0, Composer, and a couple third-party packages. I used Composer to install Slim by creating a composer.json file in the root of my application with the following:
{
"require": {
"slim/slim": "2.*"
}
}
After I ran composer install I have the following structure:
root/
vendor/
composer/
slim/
autoload.php
composer.json
composer.lock
index.php
I want to include the Valitron (https://packagist.org/packages/vlucas/valitron) library to do validation along with this Bcrypt (https://packagist.org/packages/openlss/func-bcrypt) library to hash passwords for users. So, I made the following additions to my composer.json file so the it looks like this:
{
"require": {
"slim/slim": "2.*",
"vlucas/valitron": "dev-master",
"openlss/func-bcrypt": "dev-master"
}
}
After I ran composer update I got the following directory structure.
root/
vendor/
composer/
openlss/
slim/
vlucas/
autoload.php
composer.json
composer.lock
index.php
From here, I am not sure how to set up the autoloading for my application. I sometimes see autoload classmap and other times see psr-0. On top of these third-party packages I am going to be creating my own models to use. One will be a base model that handles connecting to the database and then each table will have a model that I use to manipulate the said table with. So for interacting with the users table I will use my UserModel.php file below. My other question is how would I go about "using" the Valitron and BCrypt files within this one? Would I just do this:
<?php namespace Libraries;
use \Valitron;
use \BCrypt;
class UserModel extends BaseModel {
// I want to use the Valitron class here along with the crypt file
}
How would I go about setting up autoloader to accomplish this? Any help is greatly appreciated. I already dislike Composer a lot but since everyone is saying it's a must for PHP developers I am trying to force myself to learn it.
Composer provides an autoloader for third-party libraries specified in composer.json. See https://getcomposer.org/doc/01-basic-usage.md#autoloading. You can customise the autoloader for your needs, it supports both PSR-4 and classmap. See the autoload reference for more details.
I mean, it's pretty simple in reality. If you want these classes to be autoloaded, then require autoload.php
require 'vendor/autoload.php';
Or, in composer.json you can declare it.
{
"autoload": {
"psr-0": {"Libraries": "vendor/open-lss"}
}
}
Which will allow you to do:
namespace Libraries\func-bcrypt
class bCrypt_class{
}
which is what I believe you are attempting to achieve

Own project via composer

I've got some libraries loaded through composer, and I'm wondering if it's possible to add my own library in the /vendor map, and then to have the composer autoloader load it? The structure would be something like /vendor/mylibrary/ and then a namespace mylibrary.
Would this be possible? Also would it be possible to add a different map to the composer autoloader? Like for example /app/src/ and then to have it load all the classes in that folder? Or do I have to make my own loader for that?
Thanks
Reading the composer documentation:
You can even add your own code to the autoloader by adding an autoload field to composer.json.
{
"autoload": {
"psr-0": {"Acme": "src/"}
}
}
Composer will register a PSR-0 autoloader for the Acme namespace.
You define a mapping from namespaces to directories. The src directory would be in your project root, on the same level as vendor directory is. An example filename would be src/Acme/Foo.php containing an Acme\Foo class.
After adding the autoload field, you have to re-run install to
re-generate the vendor/autoload.php file.
So basically, you just need to follow PSR-0, and tell composer where to find your library, by adding that line to your composer.json
Yes.You can achieve it. Configure your composer.json file as following:
{
"autoload": {
"classmap": [ "classes" ]
}
Here classes is the name of the directory where you have all your application related classes.Vendor related class should be auto detected as well. Just add the following line to achieve both at the same time:
require 'vendor/autoload.php';
And you can use the namesapce to reference your class like the following:
use classes\Model\Article;
Yes, of course it is possible to add own libraries and you should feel highly encouraged to do so. If your library is available publicly, you can simply register it at packagist.org. If not, it's a bit more complicated, but not impossible.
If your project does not follow the PSR-0 standard, composer will create a classmap for you. A custom autoloader is not supported.
I'd recommend you to read the (really excellent) documentation about all this and come back, if you're running into problems.
http://getcomposer.org/doc/

Categories