【问题标题】:Deploying a Symfony app - ClassNotFoundException Error部署 Symfony 应用程序 - ClassNotFoundException 错误
【发布时间】:2018-08-04 16:02:41
【问题描述】:

我正在学习 Symfony 框架并尝试使用 Git 将我放在 Heroku 中的简单样板应用程序部署到 Heroku。

由于以下致命错误,部署失败:

Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "WebServerBundle" from namespace "Symfony\Bundle\WebServerBundle

Did you forget a "use" statement for another namespace? in /tmp/build_cbeb92af6c9ee04b07e1f85618211649/src/Kernel.php:32

内核.php

<?php

namespace App;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\RouteCollectionBuilder;

class Kernel extends BaseKernel {

    use MicroKernelTrait;

    const CONFIG_EXTS = '.{php,xml,yaml,yml}';

    public function getCacheDir(){

        return $this->getProjectDir().'/var/cache/'.$this->environment;
    }

    public function getLogDir(){

        return $this->getProjectDir().'/var/log';
    }

    public function registerBundles(){

        $contents = require $this->getProjectDir().'/config/bundles.php';
        foreach ($contents as $class => $envs) {
            if (isset($envs['all']) || isset($envs[$this->environment])) {
                yield new $class();
            }
        }
    }

    protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader){

        $container->setParameter('container.autowiring.strict_mode', true);
        $container->setParameter('container.dumper.inline_class_loader', true);
        $confDir = $this->getProjectDir().'/config';
        $loader->load($confDir.'/packages/*'.self::CONFIG_EXTS, 'glob');
        if (is_dir($confDir.'/packages/'.$this->environment)) {
            $loader->load($confDir.'/packages/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
        }
        $loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob');
        $loader->load($confDir.'/services_'.$this->environment.self::CONFIG_EXTS, 'glob');
    }

    protected function configureRoutes(RouteCollectionBuilder $routes){

        $confDir = $this->getProjectDir().'/config';
        if (is_dir($confDir.'/routes/')) {
            $routes->import($confDir.'/routes/*'.self::CONFIG_EXTS, '/', 'glob');
        }
        if (is_dir($confDir.'/routes/'.$this->environment)) {
            $routes->import($confDir.'/routes/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
        }
        $routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob');
    }
}

到目前为止我做了什么:

  • 安装 dotenv 捆绑包 (composer require symfony/dotenv)
  • 运行composer dump-autoload
  • 按照this article (heroku config:set SYMFONY_ENV=prod) 通过heroku CLI 设置生产环境变量

我学到/注意到的一些事情:

  • 根据WebServerBundle的README文件:

WebServerBundle 提供使用 PHP 运行应用程序的命令 内置网络服务器。它简化了您的本地开发设置,因为您 不必配置适当的 Web 服务器(例如 Apache 或 Nginx)来运行您的 申请。

.. 也就是说,WebServerBundle 是一个开发依赖项——但它被包含在生产环境中。

  • WebServerBundle 也包含在自动加载下的composer.lock 文件中

    "autoload": { "psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" }, ... },

  • 我的bundles.php 文件包括WebServerBundledev

    return [ Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true], Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], ];

  • 我有一个.env 文件和一个.env.dist 文件-我假设.env.dist 文件用于生产?它们都有相同的内容:

    APP_ENV=dev APP_SECRET=0473d15a4ce2723619d2e8b0405186d3

我对 symfony 很陌生,除了 dotenv 包读取 .env 文件并设置环境变量之外,我并不真正了解生产环境是如何实例化的。

对于所有这一切的任何帮助和澄清将不胜感激。

编辑:这是我的 composer.json 文件

{
    "type": "project",
    "license": "proprietary",
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "sensio/framework-extra-bundle": "^5.1",
        "symfony/asset": "^4.0",
        "symfony/console": "^4.0",
        "symfony/dotenv": "^4.0",
        "symfony/flex": "^1.0",
        "symfony/framework-bundle": "^4.0",
        "symfony/lts": "^4@dev",
        "symfony/twig-bundle": "^4.0",
        "symfony/yaml": "^4.0"
    },
    "require-dev": {
        "symfony/profiler-pack": "^1.0",
        "symfony/web-server-bundle": "^4.0"
    },
    "config": {
        "preferred-install": {
            "*": "dist"
        },
        "sort-packages": true
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/"
        }
    },
    "replace": {
        "symfony/polyfill-apcu": "*",
        "symfony/polyfill-php70": "*",
        "symfony/polyfill-php56": "*"
    },
    "scripts": {
        "auto-scripts": {
            "cache:clear": "symfony-cmd",
            "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd"
        },
        "post-install-cmd": [
            "@auto-scripts"
        ],
        "post-update-cmd": [
            "@auto-scripts"
        ]
    },
    "conflict": {
        "symfony/symfony": "*"
    },
    "extra": {
        "symfony": {
            "id": "01C1BVQJ19BG3WAS3299PDHH9P",
            "allow-contrib": false
        }
    }
}

【问题讨论】:

  • 你能给我们看看你的 composer.json 吗? web-server-bundle 来自哪里?你能发布composer why symfony/web-server-bundle 的输出吗?
  • Did you forget a "use" statement for another namespace?
  • 无法帮助解决 Heruko 问题,但 .env.dist 只是 .env 的模板文件。 .env.dist 被签入源代码管理,而 .env 没有。你不应该在 .env.dist 中有任何秘密信息,它在实际的应用程序配置中没有任何作用。通常 .env 在生产环境中根本不使用。 APP_ENV 将被设置在其他地方。我想将它设置为 prod 不会有什么坏处,但 Heruku 本身应该设置您的环境变量,并且在生产中根本不需要 .env。
  • 您是否运行过composer install 记住 git 不会管理您在开发过程中可能安装的所有捆绑包。 composer install 只会安装你的 composer.lock 说你需要的东西,它不会升级/改变任何东西
  • 我已经在上面添加了我的 composer.json 文件。 composer why symfony/web-server-bundle 的输出是“root dev-staging requires (for development) symfony/web-server-bundle (^4.0)”。我确实运行了composer install,输出如下Nothing to install or update

标签: php symfony heroku deployment symfony4


【解决方案1】:

我不确定您使用的命令,(我使用 git)

heroku 配置:设置 SYMFONY_ENV=prod

但是如果你的 .env 文件有

APP_ENV=dev

这是将环境显式设置为 dev,因此它正在尝试加载不会推送到服务器的 dev 依赖项(由您的错误证明)(阅读您提供的文章)。

您需要服务器上的.env 文件才能拥有APP_ENV=prod .env 是针对特定机器的,它被 git 忽略,而 .env.dist 被跟踪。所以编辑.env.dist 并提交它,然后一旦它在服务器上,只需将其重命名为.env,然后我将在服务器上运行composer installcomposer update,这将更新依赖关系并清除缓存。然后刷新浏览器。

【讨论】:

  • 谢谢!这有助于解决我的问题。虽然我 .env 没有被 git 忽略。我手动设置 APP_ENV=prod 并将这个文件推送到 Heroku,从而成功构建。尽管已成功部署,但对我的实时应用程序的请求会导致 403 错误。服务器日志提供以下详细信息AH01276: Cannot serve directory /app/: No matching DirectoryIndex (index.php,index.html,index.htm) found, and server-generated directory index forbidden by Options directive .. 不太确定这里缺少什么
  • @yevg run composer require symfony/apache-pack 它将创建 .htaccess 文件,看看我的回答是否有帮助 stackoverflow.com/questions/48964316/…
  • 谢谢。我确实运行了composer require symfony/apache-pack,它创建了一个.htaccess 文件,但是由于我正在上传到heroku,所以我无权访问文件树。我仍然遇到同样的错误
【解决方案2】:

答案可能取决于您如何部署应用程序,我假设您将在部署中仅安装生产依赖项,即您应该使用--no-dev 运行composer。这意味着没有安装任何开发依赖项,很可能包括 webserver-bundle,因为在使用真正的 web 服务器(如 apache 或 nginx)的生产环境中不需要它。

归结为您的代码需要此开发依赖项但未安装,或者您的网络服务器试图在错误的APP_ENV 中运行您的应用程序。

如果是后者,您应该检查您的网络服务器配置,如果您设置了适当的环境变量(至少APP_ENVAPP_DEBUG,可能还有DATABASE_URL)。在 apache 中你必须使用 SetEnv APP_ENV prod 而在 nginx 中你必须使用 fastcgi_param APP_ENV prod

编辑:我刚刚读到您使用composer,因此绝对没有安装开发依赖项,如入门指南中所述:https://devcenter.heroku.com/articles/php-support#build-behavior

因此,您不能为 Symfony 使用 dev 环境,或者您必须使用 composer 重新安装开发依赖项作为常规依赖项(绝对不推荐)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多