PHPUnit can't find my classes but autoload in composer.json looks fine - composer-php

I have the following in my composer.json:
"autoload": {
"psr-4": {
"Athena\\Core\\": "core",
"Athena\\Tests\\": "tests",
}
}
And I have this directory structure:
core/
Framework/
Console/
Commands/
AbstractCommand.php
tests/
Console/
Commands/
AbstractCommandTest.php
And when running my tests in PHPStorm, I get:
Error: Class 'Athena\Core\Framework\Console\Commands\AbstractCommand' not found
I thought maybe the vendor/autoload.php was not being loaded, but if I try to run phpunit tests --bootstrap vendor/autoload.php, I get errors saying can't declare already declared stuff so obviously it's already loaded.
What's going on? :S

Turns out, when running a globally installed phpunit, it loads the vendor/autoload from composers install location, not the project. Hence it fails to load any project class files.

Related

Composer error when trying to include multi level public personal repositories

I'm splitting up some of my personal code to modularize and reuse it on different projects.
I've started using composer recently and have been using it for referencing these modules on my projects.
The following has worked for me so far:
First project composer.json
{
"name": "mpf/apimodule",
"version":"dev-main",
"autoload": {
"psr-4": {
"APIModule\\":"classes/"
}
}
}
Second project composer.json
{
"name": "mpf/crawler",
"version":"dev-main",
"autoload": {
"psr-4": {
"API\\": "classes/"
}
},
"repositories": [
{
"type": "vcs",
"url": "git#github.com:{User}/{Repo}.git"
}
],
"require": {
"fabpot/goutte": "^3.2",
"mpf/apimodule": "dev-main"
}
}
Both composers are compiled and the project works as intended.
But when I try to add a third layer
Third project composer.json
{
"autoload": {
"psr-4": {
"API\\": "classes/"
}
},
"repositories": [
{
"type": "vcs",
"url": "git#github.com:{User}/{Repo}.git"
}
],
"require": {
"mpf/crawler": "dev-main"
}
}
I get the following error when running the composer update command
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires mpf/crawler dev-main -> satisfiable by mpf/crawler[dev-main].
- mpf/crawler dev-main requires mpf/apimodule dev-main -> could not be found in any
version, there may be a typo in the package name.
I've found a similar issue, but my repositories are all public and that was the problem for them.
I've tried running composer -vvv / composer diagnose, but couldn't find any useful information with the results.
From the description given in your question, you add repositories into root composer.json files. This works fine as long as you're using the root composer.json file. That is the project having this file.
Now while this works on each per-project basis, when you put the third (or fourth, fifth etc. ) composer.json file into the mix, or as you word it "add a third layer", it stops working.
Technically it does not stop working, however Composer can not resolve that inherited repository any longer to resolve the root dependency:
- Root composer.json requires mpf/crawler dev-main \
-> satisfiable by mpf/crawler[dev-main].
- mpf/crawler dev-main requires mpf/apimodule dev-main \
-> could not be found in any version, there may be a typo in the package name.
As honest as Composer is here, it may be puzzling in your situation. You've certainly already double-checked there is no typo and still though, Composer can not find any version.
That is because Composer uses the composer.json#/repositories configuration only from the root composer.json - that is the file itself. Let's visualize this a bit:
composer.json
vendor/mpf/crawler/composer.json
My educated guess is that, albeit you've added the repository for mpf/crawler to composer.json the repository for mpf/apimodule has not been added to it but only to vendor/mpf/crawler/composer.json.
The fix is easy, add all repositories your root project requires to resolve all dependencies to that projects configuration file (composer.json in the project you install the dependencies in).
If you think this through, it might become more clear why that is so:
The moment you install from composer.json, all repositories should be defined already as otherwise the outcome of the install will be a pure game of luck. Packages would be able to overwrite your repositories configuration and you would not be in control any longer.
My recommendations to continue your journey:
Add repositories inside your root composer.json file, to ensure your projects' configuration is complete. (Goal: understanding root configuration, the project level)
When working with this, consider if you want to have a global configuration of repositories. That is you can on the level of your computer user configure a list of repositories shared across projects (on that host). (Goal: understanding global configuration, the level of your host, working with projects)
Take a Safari-Tour on the different types of repositories Composer offers (compare with the documentation) as you may find even more in there (e.g. path repositories, another central .json file you can share etc. - there are quite some options). (Goal: understanding of the different repository configuration types)
kuba points to an entry in the Composer FAQ for this topic (via):
Why can't Composer load repositories recursively? (Composer FAQ)

Why did composer install oauth2-client with different directory names and files

I am new to composer and I used it to install the oauth2-client. I think I am having some sort of misunderstanding about how this is supposed to work.
From thephpleague github page I installed from the command line using
composer require league/oauth2-client
This added files to /usr/local/bin/vendor/league/oauth2-client.
The file structure looks the same as it does on github, except I don't have all the same files.
And the php in the files is looking for files in \League\OAuth2, so I am getting errors that it can't find included files, because I don't have that directory.
Did I do it wrong, or am I just not getting something?
The backslash is the PHP namespace separator, not the directory separator.
In the composer.json for oauth2 from TheLeague, this is the autoload directive:
"autoload": {
"psr-4": {
"League\\OAuth2\\Client\\": "src/"
}
},
It says that the code inside of src directory is in the League\OAuth2\Client namespace.
Composer follows PSR-4 with regards to namespacing and autoloading, so check that out if you want to know what goes on.
UPDATE:
If you've installed other League extensions, like oauth2-facebook, it will install itself into the same src directory - because of the autoload directive in composer.json.
Why?
Well, because of the namespace, you will find 'Facebook' in the League\OAuth2\Client\Provider namespace.
Because of PSR-4, this means that they need to go into the same directory, even though they are different packages.
That is the reason why you'll see Facebook.php in src/Providers directory. Check the oauth2-facebook repository
You probably have required oauth2-facebook and oauth2-google, or one of your other required packages requires it. It rarely just add themselves. :)

Composer private package issue

I have created a private composer package in packagist.com but when I use
composer require command to fetch it. My package coming under vendor folder which is on root.
But I want it to be in app/code folder. Is there any parameter for composer.json where I can set app/code, so it will come under app/code/.
Yes there is. According to the composer documentation, if your project uses the PSR-4 specification for loading classes, then adding the snippet below to the composer.json file would work.
NB: You will need to change ProjectNameSpace to the base namespace for your project.
...
"autoload": {
"psr-4": {
"ProjectNameSpace\\": "app/code"
}
},
...
Theoretically. You can't composer will always place the code in vendor directory. The code is external and therefore can be updated only by composer. It must not be in app/code as only code you modify for the project should be in app/code.
If you wish to make a Magento project, you should have the fallowing files in the versioning tool.
app/*
composer.json
composer.lock
.htaccess
index.php
The other files will be handled by composer.
But if you really need to do it, but I don't see any reason to do so, then you could use a post-update & post-install script to move the code. But it's a very bad idea.

How to set custom folder path for sub folders in vendor when installing a package?

I want to install a package into my local project.For that I'm creating a composer.json file in my project folder is given below, it gives the total vendor folder of that package into my custom folder in my project. Its working fine.....
{
"config": {
"vendor-dir": "/var/www/html/Test2/Testing/Down"
},
}
It gives the package into 'Down' folder.
But, now I want the sub folders or files in that packages to be installed in my custom folders like js/css folders in my project.
For example i want jquery.js file into my local folder path
/var/www/html/Test2/Testing/assests/js
From the package "frameworks/jquery".
For that, what changes are needed in my composer.json file?
Composer is used to bring in packages to support the PHP code of a project, here is how they describe it on the Composer website:
Composer is a tool for dependency management in PHP. It allows you to
declare the libraries your project depends on and it will manage
(install/update) them for you.
In other words, if you need to do logging in your PHP code and decide to use the publicly available monolog package, you use composer to bring that package into your project, then in your PHP code, you can call monolog functions.
Using config to rename the vendor directory is trying to use Composer in a way that doesn't fit the intent of the tool. The vendor directory is used to hold the packages brought in (such as the monolog code). The vendor-dir value is simply renaming that directory.
Since you have GitHub listed as a tag, you could possibly use cloning to get your files to your website directory.
I've modified my composer.json file, it looks like the below:
{
"config": {
"vendor-dir": "/var/www/html/Test2/Testing/Down"
},
"require": {
},
"scripts": {
"post-package-install": [
"php -r \"exec('cp -r /var/www/html/Test2/Testing/Down/frameworks/jquery/* /var/www/html/Test2/Testing/assets/js');\""
]
}
}
It will gives all selected files in a package to my local folder.
Briefly the files in the folder 'frameworks/jquery' are copied into my local 'assets/js' folder.

Why in laravel do you need to specify classes in composer.json

Why in laravel do you to specify classes in composer.json? I thought composer is a program that manages your project's dependencies, yet it's also used to map your controller classes for instance. Why is that?
You don't need to specify your classes in composer.json. Sure you can do that if you want but for most of the cases there is no need to do so.
Let's take a look at the autoload section of Laravels default composer.json
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
},
The classmap basically means autoload everything that's specified here. If it's a directory (like "app/controllers") it will load all classes within the folder. recursively.
So just because you want to move your controllers to subdirectories in app/controllers doesn't mean you have to change anything in composer.json
You have to do one thing though, run composer dump-autoload. You see, composer creates a file where it stores the classes and the actual file, that contains the class. You can find this file at vendor/composer/autoload_classmap.php.
The entries look like:
'IndexController' => $baseDir . '/app/controllers/IndexController.php
If you now move IndexController.php to app/controllers/foo the application will still try to include it from app/controllers until you run composer dump-autoload which will regenerate autoload_classmap.php.

Resources