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/"]
}
Related
I'm a bit confused because I'm programming a plugin for WordPress by using composer as it's the real way to go.
So I've created a composer file inside my plugin and some other stuff. In the composer file I've added my namespace for autoloading:
"autoload": {
"psr-4": {
"Johnny\\Lolkick\\": [
"includes/classes/"
]
}
}
Inside my classes folder I've created now a class with the name class-main.php. I've decided to take this name because of the WordPress naming conventions:
https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#naming-conventions
The class by itself was named class Main {. Inside my base plugin file I've created now a new instance of my class which failed. After changing the file name to Main.php it worked.
So in result the WordPress naming convention broke the autoloading of composer. I want to know now how do you handle this problem? How should I keep the naming convention by using composer?
Since your code base is not compatible with PSR-4 autoloading, a psr-4 mapping inside your composer.json's autoload section won't work, as you noticed.
I'd say you have two choices here:
First one would be to use classmap instead:
{
"autoload": {
"classmap": ["includes/classes/"]
}
}
This would simply parse all the files recursively within that folder and map the classes to their names, no matter what naming scheme you're following.
Second one would be to build your own autoloader, and use files to have it loaded automatically:
{
"autoload": {
"files": ["includes/autoloader.php"]
}
}
That autoloader would have to define what should happen (which class should be loaded, or not) when referring to a given class name.
In both cases, don't forget to run composer dump-autoload afterward.
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.
I am starting to use Composer and am a bit confused on how to specify how things should be autoloaded.
My initial assumption was that one would define how to autoload classes of a package within this package. I'm however getting the impression that one should specify this in the project where the package is used. Is that the case?
I hope not! I don't want the users of a library to know how autoloading of this library works, such as for instance in which directory the classes are located. For instance, I do not want some client to know that "MyLibrary" has its classes in a directory called "includes":
"autoload": {
"classmap": [
"vendor/MyLibrary/includes/",
]
}
If on the other hand my current impression is wrong, and thus my initial assumption correct, then my question is how to achieve this. I tried using the following in the composer.json file of one of my libraries, but upon installing it somewhere, no entries would show up in the generated autoload classmap.
"autoload": {
"classmap": [
"includes/",
]
}
My initial assumption was correct. One needs to define the autoloading for a package within the composer.json file of the package. Nothing outside of the package should know about how its autoloading is done. I am unsure why what I was doing failed to work. In any case, I have not run into this recently.
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/
I've started a new project, where I use Composer to handle some dependencies, as well as their auto-loading.
I only keep the composer.json file in the VCS, instead of the entire vendor directory, so I don't want to start adding my code in there.
How should I handle my own project specific code, so that it auto loads as well?
This is actually very simple. Excluding vendors directory from your repository is the right approach. Your code should be stored in a separate place (like src).
Use the autoload property to make that composer recognizes your namespace(s):
{
"autoload": {
"psr-4": {
"Acme\\": "src/"
}
}
}
Assuming you have class names following the psr-4 standard, it should work. Below some example of class names and their locations on the file system:
Acme\Command\HelloCommand -> src/Command/HelloCommand.php
Acme\Form\Type\EmployeeType -> src/Form/Type/EmployeeType.php
Remember to define a namespace for each class. Here's an example of Acme\Command\HelloCommand:
<?php
namespace Acme\Command;
class HelloCommand
{
}
Don't forget to include the autoloader in your PHP controllers:
<?php
require 'vendor/autoload.php';
Read more on PSR-4 standard on PHP Framework Interoperability Group.
Note that if you edit composer.json, you need to either run install, update or dump-autoload to refresh the autoloader class paths.