2

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!

Dmytro Zarezenko
  • 10,526
  • 11
  • 62
  • 104

5 Answers5

3

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:

  1. Change autoload section from your composer.json:

    {
        "autoload": {
            "psr-4": {"AAA\\DB\\": "db/"}
        }
    }
    

    where db/ is the actual path from the file system

  2. 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();
Alexandru Guzinschi
  • 5,675
  • 1
  • 29
  • 40
  • Can I somehow alias lower case folder names to uppercase in namespaces, for example I have `db/` folder but want to use it like `use AAA\DB\DBCore`? – Dmytro Zarezenko Aug 12 '15 at 06:29
2

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.

Neddage
  • 306
  • 1
  • 7
  • Can I somehow alias lower case folder names to uppercase in namespaces, for example I have `db/` folder but want to use it like `use AAA\DB\DBCore`? – Dmytro Zarezenko Aug 12 '15 at 06:29
  • 1
    You should be able to do that in your composer.json as Alexandru has described in their answer. – Neddage Aug 12 '15 at 11:39
1

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.

Community
  • 1
  • 1
edmondscommerce
  • 2,001
  • 12
  • 21
0

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/"}
    }
}
Diego Fu
  • 410
  • 2
  • 10
  • I am used the same thing, as I described before in my question. All works on the localhost (on windows), but when I upload scripts on FTP without changes (Linux server) it doesn't find classes. – Dmytro Zarezenko Aug 11 '15 at 09:55
0

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.

  • 1
    Actually Composer is just a dependency manager and its purpose ends there. Whatever you do after you have your dependencies installed, is not Composer's concern. Some people prefer to get their dependencies during deployment using `composer install`and others prefer or are forced to package everything (_no ssh access, shareware project, deliver to the client, etc_) before _pushing to production_. The real problem is when Composer is used for something that was not designed for, like installing NPM and Bower dependencies. – Alexandru Guzinschi Aug 12 '15 at 20:24
  • 1
    Actually Composer does more than just dependency management. `composer install` will generate the autoloader (which is something you seem to be having issues with) and run other scripts defined in the composer.json file. See 'options' under the [install][1] command. Have you tried running `composer install` on the production environment to see if it fixes your issue? [1]: https://getcomposer.org/doc/03-cli.md#install – iDimensionz Aug 12 '15 at 20:35
  • 1
    (_I didn't asked the question. Please pay more attention._) The scripts feature allows you to hook and change some behavior of Composer at given points in the execution lifetime, so it is an extension to the dependency management, which many dependency and package managers have it. As for the autoloader, it offers a mapping between what _crazy stuff_ any author does at the file system level and something that can be used inside the language. You can use it or you can replace it with your own at any time. – Alexandru Guzinschi Aug 13 '15 at 04:44
  • Yes, it's true, I can't run composer on production server because I have no access to do that. That's why I want to upload locally generated `vendor/` folder. – Dmytro Zarezenko Aug 13 '15 at 08:59