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.
Related
(I know others have written about this, but the answers don't seem to help in this instance)
I have a WordPress PHP plugin (https://github.com/LiquidChurch/lqd-messages/) which uses WDS-Shortcodes which in turn uses TGM-Plugin-Activation. When I run composer install from within the lqd-messages plugin I get the following error:
In ClassMapGenerator.php line 69:
Could not scan for classes inside "/lqd-messages/vendor/webdevstudios/wds-shortcodes/vendor/tgmpa/tgm-plugin-activation/class-tgm-plugin-activation.php" which does not appear to be a file or folder"
I can then go into /lqd-messages/vendor/webdevstudios/wds-shortcodes/vendor and see that there is no tgmpa folder.
If I then go back to /wds-shortcodes and run composer install, the tgmpa folder will be successfully created.
Obviously, this is less than ideal. Is there a way to get around these extra steps?
This is bug in webdevstudios/wds-shortcodes package - their autoloadig settings are incorrect. Dependencies should not declare loading files from other dependencies inside of vendor directory - this is not their concern (and these files will not exist in some scenarios, like yours).
I can only recommend forking this package and fixing autoloading settings:
"autoload": {
"classmap": ["includes/"]
},
BTW: You've made the same mistake in your package.
I'm trying to get some code set up to use an particular company's API.
I have experience with Perl and if I need a module installed, I type cpan ModuleName and most of the time it Just Works. How does that work with PHP code of similar complexity?
The company in question have a github repository with PHP Client system to access their API, which looks much the same as a perl Module.
I can git clone it, I can download it, but then what? Do I have to install it? There are no installation instructions. Or do I just start using it? There's a composer.json file in there. Do I need to run a composer command so it can figure out and install its dependencies like a CPAN module would? Will it install into system folders or just right there in whatever directory it happens to be in? I feel like there ought be some kind of official installation process because there's a /tests/ folder in the files I downloaded.
Their example code literally starts like this:
<?php
/* #var $CompanyName \CompanyName_Api */
$CompanyName = new \CompanyName_Api();
/* do interesting stuff */
and that's it. Of course nothing works if I just do that because it doesn't know where the CompanyName_Api files are. It works if I add this:
<?php
include('/full/path/to/downloaded/files/CompanyName/src/Api.php');
is that all I need to do?
In order to install all dependencies defined in composer.json you would run the following command inside the project directory:
composer install
This will find and download the dependencies into the vendor directory and it will also generate an optimized autoloader.
To autoload your own source files you'll need to add it to the autoload section in the composer.json file:
First your need to install an PHP environment like PHP, Apache and all stuff, then you need to clone that file from the git repository or just download it, then navigate to the dir and fire the command composer install. It will install all of the dependencies required for that package. After that, run the code from the browser -- the package api code may have the auto loader file which you need to include in your current package and autoloader will do all the stuff for you. Add your folder structure and file structure so that you get a better answer on this.
I've created a small command line tool in PHP and I've also packed that as a PHAR archive.
Next thing I did was publish my archive to packagist.org aka composer.
I can now install my PHAR package through composer like so:
composer global require acme/mypackage
This installs my package fine. And I'm able to run it through command as well.
So far so good, but here comes the problem I´m currently facing.
I have another project should use acme/mypackage. I want that project to reference a class that is packed into that PHAR. Something like this:
<?php
class SomeClass extends AcmeClass {
}
The problem is that the PHP code doesn't recognize the AcmeClass class. Makes sense, because it´s obviously "globally" installed somewhere on the system.
How do other libraries solve this issue? If I'm not mistaken then PHPUnit does something similar right?
How can I solve this issue?
You'll need to add a composer.json file to the root of your project:
The first (and often only) thing you specify in composer.json is the require key. You're simply telling Composer which packages your project depends on.
{
"require": {
"monolog/monolog": "1.0.*"
}
}
Next, you'll need to autoload your dependencies.
For libraries that specify autoload information, Composer generates a vendor/autoload.php file. You can simply include this file and you will get autoloading for free.
require 'vendor/autoload.php';
https://getcomposer.org/doc/01-basic-usage.md
I have two controllers with the same name:
app\controllers\CareersController.php (for public use)
app\controllers\Admin\CareersController.php (for admins)
Because of the naming conflict, I added namespace admin; to the admin controller.
Everything works fine locally but when I uploaded the new admin controller to my server, I get an error: Class Admin\CareersController does not exist
From what I understand, the fix is:
php artisan dump-autoload
and composer dump-autoload
However, I don't have Shell access to run those commands and composer isn't installed on the server anyway. So, is there a way to reload the auto-load file without Shell access?
Run composer dump-autoload locally. Then, in your hosting site,
you can update two files, autoload_classmap.php and autoload_static.php, manually in vendor/composer folder. I prefer to copy and paste the added classes from local to the hosting server.
You dont need shell access. Artisan includes a dump-autoload function. You can just it via a PHP call within your app:
Route::get('/updateapp', function()
{
\Artisan::call('dump-autoload');
echo 'dump-autoload complete';
});
Edit: just noticed you wrote "composer isn't installed on the server anyway". Not sure what will happen - try the command above and let us know.
If it doesnt work - then just run composer dump-autoload locally - then upload your new autoload.php.
As a side point - is there any option to switch servers? You going to keep running into various issues if you dont have command line & composer access. You could just use Forge and spin up a new server on DigitalOcean, Linode etc in less time than it would take to fix this issue :)
I was using a shared hosting by client's requirements and did not have access to ssh or composer, what I did was to composer dump-autoload on my local machine and then I figured that for my project autoloader just updates composer directory in my vendor directory, so I just re-uploaded that one folder after each dump-autoload and not all vendor directory
Edit:
Another pitfall for me that generated the same error but the cause was something else, I develop on Windows machine in which file and directory names are case insensitive when deploying to Linux server, the framework could actually not find my controllers so I changed
Route::get('/news', 'newsController#index');
to
Route::get('/news', 'NewsController#index');
now it is working, autoload is doing it's job correctly
I'm uploading my laravel 4 app to a testing server which is shared hosting.
I'm uploading to a password protected directory which has a .htaccess file within it. My subdomain points to the public folder.
For the most part they app is working as expected I can log in, view most of the pages however every class that I have created such as a helper class and additional controllers are not being found on the live server yet all works on my local environment.
I've redone a composer dump-autoload and uploaded the composer.json file
I'm not sure where to start with this.
In my upload I've included all the files and folders to the live server (twice now). I read somewhere else I should namespace my classes but why would this help if the main laravel controllers do not namespace?
Confused - all help appreciated
When you do a composer update, if Composer finds anything new it will update some files in the folder
vendor/composer
Like the file autoload_classmap.php.
So, you have to reupload at least this folder too.
Maybe it's about git, you are pushing changings with some certain case sensitive Folders and Files, but git is changing this therefore it will work on Mac and Windows OSs but not on the server.
just use this command:
git config core.ignorecase false
above command for the current repository and you may add --global just after config keyword.
please note that ignorecase option available since version 1.5.6 and I assume you are running 2.0.x but just mentioning!