Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Composer & Linux production server - autoload not working

I have already tried searching for this question and seen a couple of answers, but no luck...

I have composer installed with Slim Framework v3.

I am using autoload for my files using PSR-4 in the composer.json file like this:

"autoload": {
 "psr-4": {
   "App\\": "App"
 }
}

And this is my folder structure:

enter image description here

I am running it on a localhost Mac OS X El-Capitan using Apache 2.4 and everything works like magic. But when I upload it to my Production Linux server (also with Apache 2.4), the autoload seems to be extremely confused and I am getting errors like these:

Warning: include(/home/friendsapp/public_html/vendor/composer/../../app/Middleware/AuthMiddleware.php): failed to open stream: No such file or directory in /home/friendsapp/public_html/vendor/composer/ClassLoader.php on line 412

Warning: include(): Failed opening '/home/friendsapp/public_html/vendor/composer/../../app/Middleware/AuthMiddleware.php' for inclusion (include_path='.:/usr/lib/php:/usr/local/lib/php') in /home/friendsapp/public_html/vendor/composer/ClassLoader.php on line 412

Fatal error: Class 'App\Middleware\AuthMiddleware' not found in /home/friendsapp/public_html/public/index.php on line 5

I have namespaced my classes exactly according to my folder structure.

<?php

namespace App\Middleware;

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

use \App\Middleware\Middleware;

use \App\Share\ErrorCode;
use \App\Models\ResultMessage;

use \App\Mappers\AccessTokenMapper;

class AuthMiddleware extends Middleware {

Any help would be most appreciated! :)

like image 647
Erez Hod Avatar asked Jun 08 '26 05:06

Erez Hod


2 Answers

Looking at the path in the errors /app/Middleware/AuthMiddleware.php

It appears the issue is caused by a namespace conflict of App\\ being pointed to /app in your production environment as opposed to your PSR-4 declaration pointing to /App.

To avoid conflicts and map all of the namespaces of a specified directory you can use the autoload classmap or config optimize-autoloader (optional) options in composer.json in order to define the physical path of all the files and objects in the specified directories for composer to load. Additionally with the PSR-4 declaration, any files not found in the classmap paths will be attempted to be loaded from the App namespace path declaration(s). For example when using the exclude-from-classmap option.

"config": {
    "optimize-autoloader": true
},
"autoload": {
    "psr-4": {
        "App\\": "App/"
    },
    "classmap": [
        "App/",
    ],
}

After making the change in your composer.json, be sure to run php composer.phar update --lock in your development environment.

Then after uploading the composer.lock and composer.json files to your production environment, run php composer.phar install --no-dev -o or php composer.phar dump-autoload --no-dev -o from the production environment.

The -o option will force the optimize-autoloader classmapping to run and --no-dev will prevent the development packages (require-dev) from being installed. Using optimize-autoloader is recommended for production environments.


As a general practice, anytime you deploy your development changes to your production environment you need to run php composer.phar install --no-dev -o See How to deploy correctly when using Composer's develop / production switch?. This way the changes applied from your development environment using php composer.phar update are installed in your production environment correctly.

like image 127
Will B. Avatar answered Jun 10 '26 05:06

Will B.


For my production server the following worked:

composer install --no-dev -o

then restart php

on serverpilot:

rm -rf vendor/*
composer5.6-sp install --no-dev -o
sudo service php5.6-fpm-sp restart
like image 28
Haroldo Avatar answered Jun 10 '26 07:06

Haroldo