0
votes

what's exactly the difference in class autoloading and namespace handling between symfony2's app_dev.php and app.php or dev/prod environment (symfony 2.8.4).

When I run it in dev environment through app_dev.php all is fine, when I run it in prod through app.php I get an Internal Server error 500 (nothing written in symfony's prod.log). Looking into apache's error.log I see:

PHP Fatal error:  Class 'SSMCRM\\Common\\ProductionTemplateMapper' not found in /var/[...]

And yes, I cleared the prod cache...

app.php:

use Symfony\Component\HttpFoundation\Request;

/**
 * @var Composer\Autoload\ClassLoader
 */
$loader = require __DIR__.'/../app/autoload.php';
include_once __DIR__.'/../app/bootstrap.php.cache';

// Enable APC for autoloading to improve performance.
// You should change the ApcClassLoader first argument to a unique prefix
// in order to prevent cache key conflicts with other applications
// also using APC.
/*
$apcLoader = new Symfony\Component\ClassLoader\ApcClassLoader(sha1(__FILE__), $loader);
$loader->unregister();
$apcLoader->register(true);
*/

//require_once __DIR__.'/../app/AppCache.php';

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
//$kernel = new AppCache($kernel);

// When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter
//Request::enableHttpMethodParameterOverride();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

app_dev.php:

<?php

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Debug\Debug;

// If you don't want to setup permissions the proper way, just uncomment the following PHP line
// read http://symfony.com/doc/current/book/installation.html#checking-symfony-application-configuration-and-setup
// for more information
//umask(0000);

// This check prevents access to debug front controllers that are deployed by accident to production servers.
// Feel free to remove this, extend it, or make something more sophisticated.
if (isset($_SERVER['HTTP_CLIENT_IP'])
    || isset($_SERVER['HTTP_X_FORWARDED_FOR'])
    || !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1',
                                                  '192.168.33.1', //for vagrant box
        )) || php_sapi_name() === 'cli-server')
) {
    header('HTTP/1.0 403 Forbidden');
    exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
}

/**
 * @var Composer\Autoload\ClassLoader $loader
 */
$loader = require __DIR__.'/../app/autoload.php';
Debug::enable();

$kernel = new AppKernel('dev', true);
$kernel->loadClassCache();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

in the autoload.php I added our legacy classes to the loader:

$loader->add('SSMCRM', __DIR__.'/../web/legacy/classes');
1
It looks like your autoloading isn't setup correctly in your app.php file. Please could you supply the contents of both the app.php & app_dev.php files.LMS94
I added the contents of app.php/app_dev.phpedditor
Have you tried realpath()? $loader->add('SSMCRM', realpath(DIR.'/../web/legacy/classes')); Also, it's concerning to see you're storing legacy class in a public dir (web).LMS94
Another thing to try is warming up the cache, or forcefully removing the cache: rm -rf app/cache/*LMS94
I tried the realpath thing with no effect. And I also tried both methods to clear the cache, with rm and with the symfony command with warmup. Yes it may sound weird to store the classes in the web folder, but we're refactoring our legacy code and wrap it with symfony so we have access to all legacy classes in symfony and to all symfony features in the legacy code. The parts which aren't already wrapped are called directly from webfolder through a special route.edditor

1 Answers

0
votes

I found the failure. For each legacy PHP file which was called directly now we have a route which leads to our wrapper (to make the symfony features available in the legacy code). I generated the controller and it's routenames and paths from the real URLs so in the first step we didn't need to rewrite all links and javascript AJAX calls and to make find/replace actions easier later. The result is sth. like that:

/**
 * @Route(
 * path="ajax/ajax_admin_vorlagen_web2print_detail.php",
 * name="pages/admin/ajax/ajax_admin_vorlagen_web2print_detail.php",
 * options={"expose"=true}
 * )
 */
public function ajax_admin_vorlagen_web2print_detailAction()
{
    return $this->returnLegacyResponse('pages/admin/ajax/ajax_admin_vorlagen_web2print_detail.php');
}

This works absolutely fine in dev environment, symfony's routing is executed and we get to the corresponding action. But it seems that in prod environment symfony looks first for the file itself (maybe for better speed?) and skips the route matching if the file exists. If our file is called directly there is no symfony autoloader and we removed recently our legacy autoloader. That's why the class is missing...

So the simple solution is to rename all affected paths (e.g. remove the ".php").

I couldn't find anything about this differences between prod/dev environment in kernel processing in the docs. :(