【问题标题】:PHP Autoloader doesn't work on Ubuntu production serverPHP Autoloader 在 Ubuntu 生产服务器上不起作用
【发布时间】:2015-09-06 20:38:13
【问题描述】:

我必须在我正在开发我的 API(基于 PHP)的环境中工作:

  1. 本地开发: Mac OS Yosemite - 运行 PHP 5.5.20
  2. 生产服务器: Ubuntu 服务器 - 运行 PHP 5.5.9

我的代码使用 composer 进行自动加载,如下所示:

{
    "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"
        }
    }
}

这是我的加载函数:

// 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'),
);

当我在本地开发中运行我的代码时 - 它运行良好,所以我将它推送到我的远程存储库并从生产服务器中提取它。

当我尝试在生产服务器中运行我的代码时,我收到一个 Class not found 错误,表明我的自动加载没有正常运行。

任何想法可能是什么原因?

更新: 当我尝试加载外部库(如 AWS)时,它确实可以工作,所以问题在于我的文件夹是如何加载的。

更新: 这是我试图从 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()));
}

这是我收到的错误Class 'PicoCore\Rest\ApiInitializer' not found

结构是:

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

【问题讨论】:

  • 99% 确定它与目录分隔符或硬编码的基本路径有关。我不使用作曲家,但那些/ 是目录分隔符吗?你能发布你的自动加载功能吗?
  • @redelschaap 我添加了它。我希望你的意思是:)
  • 我认为问题出在最后一部分。你能把所有的/改成DIRECTORY_SEPARATOR吗?所以$vendorDir . '/aws/aws-sdk-php/src' 变成了$vendorDir . DIRECTORY_SEPARATOR . 'aws' . DIRECTORY_SEPARATOR . 'aws-sdk-php' . DIRECTORY_SEPARATOR . 'src'。您能否验证$vendorDir 在生产服务器上的基本路径是否正确?
  • $vendorDir 和 $baseDir 是正确的。供应商不是我的问题。它找不到我自己的文件,也找不到其他库。我尝试按照您在 'PicoCore\\Rest\\' => array($baseDir . '/PicoCore/rest') 中的建议进行操作,因为这是他正在寻找的命名空间,但它没有用
  • @redelschaap 外部库的工作原理.. 它与我的类定义完全不同

标签: php ubuntu composer-php


【解决方案1】:

这是你错误的自动加载定义。

你想使用类

PicoCore\Rest\ApiInitializer

你有这些文件:

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

你已经配置了这个自动加载:

“自动加载”:{ “psr-0”:{ "PicoCore\Rest\" : "PicoCore/rest" } }

这是不匹配的。当您使用类PicoCore\Rest\ApiInitializer 时,composer 将尝试查找具有该类前缀的条目。它将成功检测到前缀为PicoCode\Rest 的类可以通过目录中的PSR-0 规则找到(相对于composer.json 的位置)PicoCore/rest

第一个奇怪的事情:这里有一个名为“core”的附加目录,您似乎包含两个自动加载器。不要那样做,Composer 最好只使用一个自动加载器。

第二件事:如果我暂时忽略那个“核心”目录,PSR-0 规则规定类名将被转换为路径 - 然后在给定前缀的路径中搜索。

PicoCore\Rest\ApiInitializer 作为路径是PicoCore/Rest/ApiInitializer.php(注意“Rest”中的大写“R”),要找到的路径是PicoCore/rest/PicoCore/Rest/ApiInitializer.php

您没有此文件。这就是 Composer 无法找到并加载它的原因。而且即使不计算这个“核心”目录级别,如果你使用了两个composer.json文件,一个在api,一个在api/core,一个在api/core的文件,也是找不到的。找到课程。

建议:

  1. 对命名空间内的每个类都使用 PSR-4。
  2. 文件系统的命名空间或类名部分不要小写。
  3. 缩短自动加载定义。如果您将PicoCore 下方的所有小写目录重命名为您的命名空间中使用的正确大写变体,您将只需要一行自动加载定义,定义PicoCore 前缀。其余部分由 PSR-4(或 PSR-0)完成。

MacOS 默认使用不区分大小写的文件系统,将其切换为区分大小写被认为是一件坏事:https://apple.stackexchange.com/questions/71357/how-to-check-if-my-hd-is-case-sensitive-or-not 这就是为什么它可以在 Mac 上运行,而不是在 Linux 上运行。

【讨论】:

  • 感谢您的详细回答。我现在将尝试实施它。关于 2 个核心,我们有多种类型的服务,它们使用相同的核心 (PicoCore) 作为子树。 PicoCore 有它的依赖关系,具体的服务有它自己的依赖关系。我很乐意从作曲家的角度了解如何以不同的方式设计它。如果我要重命名文件夹,我只需要这一行: "PicoCore\\": "", ?
  • 用composer完成重命名重新安装,它现在可以工作了。还修改了作曲家以包含在命名空间前缀中,它就像一个魅力
  • 将 PicoCore 添加为依赖项,不要将其放在单独的目录中。如果这会为项目添加太多未使用的代码,请考虑将其分成相互依赖的单个包(但不是全部)。
  • 如何从我的 PicoCore 创建一个私有包,以便将其添加为依赖项?
猜你喜欢
  • 1970-01-01
  • 2016-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 2020-05-20
相关资源
最近更新 更多