duanbi3151 2015-06-21 07:30
浏览 46
已采纳

PHP Autoloader不适用于Ubuntu生产服务器

I have to environments i'm working developing my API (PHP based):

  1. Local development: Mac OS Yosemite - running PHP 5.5.20
  2. Production server: Ubuntu server - running PHP 5.5.9

My code uses composer for auto loading as followed:

{
    "require": {
        "facebook/php-sdk": "@stable",
        "everyman/neo4jphp": "dev-master",
        "predis/predis": "1.0.1",
        "aws/aws-sdk-php": "2.*"
    },

    "autoload": {
        "psr-0": {
            "PicoCore\\": "",
            "PicoCore\\Authentication\\" : "PicoCore/authentication",
            "PicoCore\\Aws\\" : "PicoCore/aws",
            "PicoCore\\Cache\\" : "PicoCore/cache",
            "PicoCore\\Database\\" : "PicoCore/database",
            "PicoCore\\Database\\Managers\\" : "PicoCore/database/managers",
            "PicoCore\\Facebook\\" : "PicoCore/facebook",
            "PicoCore\\Objects\\" : "PicoCore/objects",
            "PicoCore\\Rest\\" : "PicoCore/rest",
            "PicoCore\\Configuration\\" : "PicoCore/configuration",
            "PicoCore\\Configuration\\Api\\" : "PicoCore/configuration/api",
            "PicoCore\\Configuration\\PictureReceiver\\" : "PicoCore/configuration/pictureReceiver",
            "PicoCore\\Configuration\\PictureUploader\\" : "PicoCore/configuration/pictureUploader",
            "PicoCore\\Scripts\\" : "PicoCore/scripts",
            "PicoCore\\Times" : "PicoCore/times"
        }
    }
}

This is my loading function:

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'PicoCore\\Times' => array($baseDir . '/PicoCore/times'),
    'PicoCore\\Scripts\\' => array($baseDir . '/PicoCore/scripts'),
    'PicoCore\\Rest\\' => array($baseDir . '/PicoCore/rest'),
    'PicoCore\\Objects\\' => array($baseDir . '/PicoCore/objects'),
    'PicoCore\\Facebook\\' => array($baseDir . '/PicoCore/facebook'),
    'PicoCore\\Database\\Managers\\' => array($baseDir . '/PicoCore/database/managers'),
    'PicoCore\\Database\\' => array($baseDir . '/PicoCore/database'),
    'PicoCore\\Configuration\\PictureUploader\\' => array($baseDir . '/PicoCore/configuration/pictureUploader'),
    'PicoCore\\Configuration\\PictureReceiver\\' => array($baseDir . '/PicoCore/configuration/pictureReceiver'),
    'PicoCore\\Configuration\\Api\\' => array($baseDir . '/PicoCore/configuration/api'),
    'PicoCore\\Configuration\\' => array($baseDir . '/PicoCore/configuration'),
    'PicoCore\\Cache\\' => array($baseDir . '/PicoCore/cache'),
    'PicoCore\\Aws\\' => array($baseDir . '/PicoCore/aws'),
    'PicoCore\\Authentication\\' => array($baseDir . '/PicoCore/authentication'),
    'PicoCore\\' => array($baseDir . '/'),
    'Guzzle\\Tests' => array($vendorDir . '/guzzle/guzzle/tests'),
    'Guzzle' => array($vendorDir . '/guzzle/guzzle/src'),
    'Everyman\\Neo4j' => array($vendorDir . '/everyman/neo4jphp/lib'),
    'Aws' => array($vendorDir . '/aws/aws-sdk-php/src'),
);

When i'm running my code on my local development - it works perfectly, so I pushed it to my remote repository and pull it from the production server.

When i'm trying to run my code in my Production server I receive a Class not found error indicating that my autoloading didn't run properly.

Any ideas what could be the reason ?

UPDATE: When i'm trying to load the external libs (like AWS) it does work, so the problem is defiantly something with how my folders are being loaded.

UPDATE: This is the class i'm trying to load from index.php:

<?php
//require Pico Core autoload
require 'core/vendor/autoload.php';

//require Pico Api autoload
require 'vendor/autoload.php';

use PicoCore\Rest\ApiInitializer;
use PicoCore\Configuration\Error;
use PicoApi\Managers\ApiManager;

try {
    //initialize the API
    ApiInitializer::initialize();
    //initialize a new Api with the request
    $api = new ApiManager($_REQUEST['request']);
    echo utf8_encode($api->processApi());

} catch (Exception $e) {
    echo json_encode(Array(Error::jsonErrorField() => $e->getMessage()));
}

This is the error I receive Class 'PicoCore\Rest\ApiInitializer' not found

The structure is:

api
 |
 core
   |
   PicoCore
      |
     folders..
     rest
      |
      ApiInitializer.php
     folders...
    vender
 PicoApi (folder)
 vendor (foldeR)
 index.php
  • 写回答

1条回答 默认 最新

  • douzhou7037 2015-06-21 21:09
    关注

    It's your wrong autoloading definition.

    You want to use the class

    PicoCore\Rest\ApiInitializer
    

    And you have these files:

    api/index.php
    api/vendor/...    (with your required external dependencies)
    api/composer.json (with the autoloading mentioned in your question)
    api/core/PicoCore/rest/ApiInitializer.php
    

    And you have this autoloading configured:

    "autoload": { "psr-0": { "PicoCore\Rest\" : "PicoCore/rest" } }

    This is a mismatch. When you use the class PicoCore\Rest\ApiInitializer, composer will try to locate an entry with a prefix of that class. It will sucessfully detect that classes with prefix PicoCode\Rest can be found via PSR-0 rules in the directory (relative to the position of composer.json) PicoCore/rest.

    First strange thing: There is an additional directory named "core" here, and you seem to include TWO autoloaders. Don't do that, Composer works best with only one autoloader.

    Second thing: If I ignore that "core" directory for a bit, the PSR-0 rules state that the classname will be converted to a path - and then be searched in the path given for the prefix.

    PicoCore\Rest\ApiInitializer as a path is PicoCore/Rest/ApiInitializer.php (note the uppercase "R" in "Rest"), and the path this is to be found is PicoCore/rest/PicoCore/Rest/ApiInitializer.php.

    You don't have this file. And thats why Composer cannot find and load it. And this is even without counting this "core" directory level, it will also not be found if you used two composer.json files, one in api and one in api/core, and the one in api/core was used to find the class.

    Suggestions:

    1. Use PSR-4 for every class that is inside a namespace.
    2. Don't lowercase namespace or classname parts for the filesystem.
    3. Shorten your autoloading definition. If you'd rename all those lowercase directories below PicoCore into the proper uppercase variants that are being used in your namespace, you will only need one line of autoloading definition, defining the PicoCore prefix. The rest is done by PSR-4 (or PSR-0).

    MacOS is using a case insensitive file system by default, and it is considered a bad thing to switch it to case sensitive: https://apple.stackexchange.com/questions/71357/how-to-check-if-my-hd-is-case-sensitive-or-not That's why it is working on Mac, but not Linux.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行