Using composer to autoload library outside of vendor/ folder - php

Vagrant and mounted folders do not play nice with composer using relative paths to folders added in via the
"autoload" option.
It in-correctly detects what the baseDir is and therefore will fail to register the namespaces.
Has anyone come across this before?
For isntance
"autoload": {
"psr-4": { "Inventory\\" : "./core/src/inventory/" }
}

The autoloading is supposed to be given relative to the path where the composer.json file is located. I've never seen that path starting with a dot, so first of all I'd try to get rid of that and see how that works.
Second thing that might simply be is that you got the autoloading wrong in some detail and mistake it for being something related to Vagrant. The way you currently set it up, a class named \Inventory\Foo must be located in the path core/src/inventory/Foo.php. Can you verify that this is the case? Otherwise please give an example of an existing class name and it's file name.

Related

Issues doing require_once in a Laravel folder

I have a situation where I've been forced to use something that SHOULD be a composer package in my Laravel project, instead, as just part of my project files (the composer package as far as I can tell contains bugs that I cannot resolve and I'm using a folder of similar php files my colleague provided to me)
I'll try to give as much context as I can:
I've installed all the files into a folder at this directory: \app\Channels\V1\Helpers\MarketplaceWebService\. The files are similar to this project, but different
In order to get the classes in the above folder loaded, I've added a line to my composer.json file:
"autoload": {
"psr-4": {
"App\\": "app/"
},
"classmap": [
"database/seeds",
"database/factories",
"app/Channels/V1/Helpers/MarketplaceWebService"
]
},
That last line in the classmap array - I used that to load my classes into my project, so I can now require them via use MarketplaceWebService_Client; at the top of any of my normal laravel files
Now for a lot of cases, this works -- I can initiate classes and they pull from the correct place.
However, any time I use one of the MarketplaceWebService that have a relative require_once, it fails
I have ANOTHER composer package by the same guy, tilluels, called amazon-mws-orders, and it looks based on the error message I'm receiving that these relative require_once calls are for some strange reason being made relative to that package, rather than relative to the location of the file I'm in.
So for example, if a file has require_once ('Interface.php');, and Interface.php is in the same folder as that file, it works just fine, BUT if a file has require_once ('../Model.php'), I get this lovely message:
500 - {"message":"MarketplaceWebService_Client::main():
Failed opening required '../Model.php'
(include_path='/home/devchannelapi/laravel/vendor/tilleuls/amazon-mws-orders/src:.:/opt/alt/php72/usr/share/pear')",exception":"Symfony\\Component\\Debug\\Exception\\FatalErrorException",
"file":"/home/devchannelapi/laravel/app/Channels/V1/Helpers/MarketplaceWebService/Model/SubmitFeedResponse.php","line":22
And I set some breakpoints in Xdebug and it is, in fact, line 22 on /Model/SubmitFeedResponse.php where it says require_once('../Model.php'), and the Model.php class is indeed one directory above that file, so you'd expect the require_once statement to work. And in fact, if I make a copy of Model.php and put it into the /Model folder, and change the require statement to require_once('Model.php'), it actually DOES work! But whenever I leave the relative requires, it gives me an error message like above, as if it's looking for relative requires in /home/devchannelapi/laravel/vendor/tilleuls/amazon-mws-orders/src
Now I've already done composer dump-autoload, I don't know enough about Laravel class loading to understand why else this might be happening.
Any help would be appreciated.
I was able to replace all relative imports with __DIR__ imports
eg require_once('../Model.php); becomes require_once(__DIR__ . '/../Model.php);
Was a bit of a pain to edit every file in the folder, but Sublime Text was a great help!

PHP Notice: Constant FLD_EMAIL already defined laravel

I have created a file called db-constant.php in conifg directory in laravel , this file contains my constants,then i added this line require_once 'db-constants.php'; in app.php ,the problem is where i type php artisan cache:clear or any command this message will appear
PHP Notice: Constant FLD_EMAIL already defined in /var/www/html/test/config/db-constants.php on line 1
how can i fix this ?
If you use Laravel, you don't have to use require_once or it's counterparts. composer's autoloading is used for everything, and configuration files are loaded automatically. What you have to do is read the docs about configuration, place the file in config/ directory and return an array with configuration values.
Now, what it seems (to me at) is that for some odd reason you want to use constants instead of Laravel's mechanism for accessing configuration values. In that case, you:
1.) DON'T place anything in config/ directory
2.) DON'T manually require_once anything
3.) DO use Composer's autoloading capabilities
How to load a file with constants in Laravel
1.) create app/MyConstants directory.
2.) create your file, let's call it constants.php. Path is:
app/MyConstants/constants.php
3.) Add your define code
4.) Open composer.json
5.) Find "autoload"
6.) Look for "files" under "autoload". If it doesn't exist, create it.
7.) Add the list of files you want to include automatically
Your "autoload" in composer.json should look like this:
"autoload": {
"files": ["app/MyConstants/constants.php"]
}
In terminal, type composer du or composer dump-autoload. It will re-create autoloader and automatically include the file with your constants.
Remove bootstrap/cache so you can use artisan again.
Now you can:
1.) Have a place where you can define constants
2.) Avoid manually requiring files
Personally, I don't see a reason for this, but then again - I'm just a human, I've no clue about anything in the grand scheme :)
You need to read this docs first https://laravel.com/docs/5.4/configuration. As well as the rest of the documentation for Laravel. How to use config files:
Create your own file db-constant.php in config directory.
Fill it as you need. For example
return [
'FLD_EMAIL' => 'your-field-here',
];
Use it wherever you need
$email = config('db-constant.FLD_EMAIL');
It's all.

Composer vendor/ folder FTP upload

I have a local project with loaded with Composer libs. I uploaded this project to my FTP and received errors, connected with not found classes from some libs.
Can I simply copy vendor/ folder to FTP or I missed something?
Error received:
Fatal error: Class 'AAA\Core\Tools' not found in /home/aaa/public_html/api.php on line 11
api.php:
<?php
use AAA\Core\Tools;
require_once("./vendor/autoload.php");
require_once("./api/" . Tools::getFieldValue('controller') . ".php");
All works fine on localhost!
Linux has a case sensitive file system. That means that files Alex.txt and alex.txt are the same thing in Windows, but not in Linux. Actually on Linux both can happily live in the same directory:
$ tree .
.
├── alex.txt
└── Alex.txt
0 directories, 2 files
Taking this into consideration, I would try to double check that the paths you are using in your namespace are actually identical to what is found at the file system level. (i.e: AAA directory with only uppercase letters ; Core directory capitalized and Tools.php file capitalized)
If you want to keep your existing file system layout, you can use PSR-4 to explicitly tell Composer how to map the namespace to the file system:
Change autoload section from your composer.json:
{
"autoload": {
"psr-4": {"AAA\\DB\\": "db/"}
}
}
where db/ is the actual path from the file system
Update the autoloader:
$ composer dump-autoload
This will take care of directory names, but doesn't apply for files. Meaning that any file inside db/ must be named exactly as used in namespace (for a usage as use AAA\DB\DBCore the file must be db/DBCore.php).
If your file is named dbcore.php and you want to reference it in your namespace as DBCore, you can use classmap feature from Composer:
"autoload": {
"classmap": [
"db/dbcore.php"
]
}
dbcore.php:
<?php
namespace AAA\DB;
class DBCore
{
}
And you can use it as usual:
<?php
require_once("./vendor/autoload.php");
$dbCore = new \AAA\DB\DBCore();
Firstly I would check the autoloader files composer has generated to make sure the paths are valid on your linux server.
Another simple but common issue is that on windows the folder and file names are not case sensitive however they are on Linux. Double check that the folders and files have the correct case as if not it won't find them to auto load.
Rather than trying to upload via FTP which I think is going to be tricky if not impossible to get right, I would suggest you explore getting composer working on your hosting environment.
Composer is entirely PHP based, so should run anywhere that PHP is running.
If you don't have command line access, you can use something like PHPShell which gives you a PHP based command line on which you can then run Composer.
See this other SO answer to get some tips on how to use PHPShell.
Another option is to build a little PHP wrapper that you actually run by visiting it in your browser, in the classic PHP way. See this other SO answer for some tips on how to do that.
Bottom line, you should really look at getting Composer running on your server rather than trying to bodge it another way.
Once you have done your composer process on the server, you must remove the PHPShell or composer wrapper you created so that you don't leave any security holes.
Did you tell the composer where your Class 'AAA\Core\Tools' is?
You can even add your own code to the autoloader by adding an autoload field > to composer.json.
{
"autoload": {
"psr-4": {"Acme\\": "src/"}
}
}
Composer is not meant to be used that way (i.e. you shouldn't be manually transferring vendor directories from one environment to another).
As you add dependencies to your project, the composer.json file will contain those dependencies. When you run composer install or update on your localhost, it "locks" the current version of those dependencies for your project and stores them in the composer.lock file. You should be transferring the composer.json and composer.lock files from your development environment to your production environment and then running composer install on your production environment as part of your deployment process. When you run composer install on your production environment, Composer will look at your composer.lock file and install the specified versions of the dependencies in the vendor directory of the production environment.
You may want to review the composer documentation regarding basic usage (https://getcomposer.org/doc/01-basic-usage.md) and command line options (https://getcomposer.org/doc/03-cli.md) for more details.

Composer: How to recursively autoload subfolders in /src

I'm writing some tests for a composer package, but i cannot load classes in subfolders of /src.
My folder structure
root
- src
- file1.php
- folder1
- folder2
- file2.php
- tests
The tests' folder structure reflects the one of src.
In my composer.json i've:
{
"autoload": {
"psr-4": {
"Namespace1\\\Package_Namespace\\\": "src"
}
}
}
Now, when i launch the tests, only the ones in src can well include their own classes, while the ones that use the classes in subfolders can't (for example, file2.php is never loaded).
I've tried also to explicitly specify the subfolders in composer.json file, but it seems not working.
I hope someone can help me. If you need more info, please let me know and i'll provide them.
Thank you and i wish you a merry Christmas!
I think you may need to escape the namespace in the config:
"autoload": { "psr-4": { "Namespace1\\Package_Namespace\\": "src" } }
and make sure your classes / filenames follow PSR-4. Also, be sure PHPUnit / whatever test suite you're running loads the composer autoload file.
ETA:
You can also manually add your tests to the namespace in the bootstrap.php file (if you're using one for your tests):
$loader = require __DIR__ . "/../vendor/autoload.php";
$loader->addPsr4('Namespace1\\Package_Namespace\\', __DIR__.'/testdir');
Obviously you'll need to adjust the above accordingly to your paths.
I think there is something wrong with the way Composer loads psr-4 maps.
Infact i've changed namespace reflecting the folder structure and now all work well.
I think namespace can be different from folder structure, but this doesn't work.
I cannot better explain my solution, but only that reflecting the folder structure works. Is it a casuality? Mah!
Anyway, it now works...

Symfony 2.3 - after moving vendors dir autoloading MyBundle got broken

I wanted to make vendor directory common for more than one project. So I moved it and updated my app/autoload.php accordingly: ($loader = require __DIR__.'/../../../vendor/autoload.php')
It worked to some degree - it seems Symfony was able to find it's way to vendors directory BUT somewhere along the way autoloading my bundles got broken. I get this:
FatalErrorException: Error: Class 'My\FooBundle\MyFooBundle' not found
in (...)\Symfony\app\AppKernel.php line 19
How should I solve this? Should I somehow add dir with my bundles to app/autoload.php?
I understand that Composer is responsible for autoloading anything within vendors dir, but not my bundles, so I guess that messing with composer.json doesn't make sense, right?
You should check the vendor/composer/autoload_namespace.php file. The $vendorDir should stay the same, but the $baseDir certainly needs to be changed.
Make sure the line "psr-0" in composer.json point to correct path. In your case, I guess it should be YourBundleFolder/src. Normally it's just src because src is same level with composer.json. Now you have moved the vendor folder, I guess you moved the composer.json also. That's why it can not find your bundle.

Categories