部署 Symfony 应用程序 - ClassNotFoundException 错误
Deploying a Symfony app - ClassNotFoundException Error
我正在学习 Symfony 框架,并尝试使用 Git 将我放在一起的简单样板应用程序部署到 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
Kernel.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 设置生产环境变量
我 learned/have 注意到了一些事情:
- 根据
WebServerBundle
的自述文件:
WebServerBundle provides commands for running applications using the PHP
built-in web server. It simplifies your local development setup because you
don't have to configure a proper web server such as Apache or Nginx to run your
application.
.. 也就是说,WebServerBundle
是开发依赖项 - 但它已包含在生产中。
WebServerBundle
也被包含在自动加载
下的 composer.lock
文件中
"autoload": {
"psr-4": {
"Symfony\Bundle\WebServerBundle\": ""
},
...
},
我的 bundles.php
文件包括 WebServerBundle
for dev
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 和 --no-dev
是您应该的。这意味着安装了 none 的开发依赖项,其中很可能包括 webserver-bundle,因为在使用真实网络服务器(如 apache 或 nginx)的生产环境中不需要它。
归根结底是您的代码需要此未安装的开发依赖项,或者您的网络服务器正在尝试 运行 您的应用程序错误 APP_ENV
。
如果是后者,如果您设置了适当的环境变量(至少 APP_ENV
和 APP_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 重新安装 dev-dependencies 作为常规依赖项(绝对不推荐)。
我不确定您使用的命令,(我使用 git)
heroku config:set SYMFONY_ENV=prod
但是如果你的 .env 文件有
APP_ENV=dev
这是明确地将环境设置为开发,因此它正在尝试加载开发依赖项(由您的错误证明),这些依赖项不会被推送到服务器(阅读您提供的文章)。
您需要服务器上的 .env
文件才能具有 APP_ENV=prod
.env 是针对特定机器的,它被 git 忽略,而 .env.dist 被跟踪。所以编辑 .env.dist
并提交它,一旦它在服务器上,只需重命名它 .env
然后我会 运行 composer install
或 composer update
在服务器上将更新依赖项并清除缓存。然后刷新浏览器。
我正在学习 Symfony 框架,并尝试使用 Git 将我放在一起的简单样板应用程序部署到 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
Kernel.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 设置生产环境变量
我 learned/have 注意到了一些事情:
- 根据
WebServerBundle
的自述文件:
WebServerBundle provides commands for running applications using the PHP built-in web server. It simplifies your local development setup because you don't have to configure a proper web server such as Apache or Nginx to run your application.
.. 也就是说,WebServerBundle
是开发依赖项 - 但它已包含在生产中。
下的WebServerBundle
也被包含在自动加载composer.lock
文件中"autoload": { "psr-4": { "Symfony\Bundle\WebServerBundle\": "" }, ... },
我的
bundles.php
文件包括WebServerBundle
fordev
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 和 --no-dev
是您应该的。这意味着安装了 none 的开发依赖项,其中很可能包括 webserver-bundle,因为在使用真实网络服务器(如 apache 或 nginx)的生产环境中不需要它。
归根结底是您的代码需要此未安装的开发依赖项,或者您的网络服务器正在尝试 运行 您的应用程序错误 APP_ENV
。
如果是后者,如果您设置了适当的环境变量(至少 APP_ENV
和 APP_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 重新安装 dev-dependencies 作为常规依赖项(绝对不推荐)。
我不确定您使用的命令,(我使用 git)
heroku config:set SYMFONY_ENV=prod
但是如果你的 .env 文件有
APP_ENV=dev
这是明确地将环境设置为开发,因此它正在尝试加载开发依赖项(由您的错误证明),这些依赖项不会被推送到服务器(阅读您提供的文章)。
您需要服务器上的 .env
文件才能具有 APP_ENV=prod
.env 是针对特定机器的,它被 git 忽略,而 .env.dist 被跟踪。所以编辑 .env.dist
并提交它,一旦它在服务器上,只需重命名它 .env
然后我会 运行 composer install
或 composer update
在服务器上将更新依赖项并清除缓存。然后刷新浏览器。