Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Bootstrap autoloader issue in production
  • Hi,

    My app/bootstrap.php contain the following :

    <?php
    // Bootstrap the framework DO NOT edit this
    require COREPATH . 'bootstrap.php';

    \Autoloader::add_classes( [
    // Add classes you want to override here
    'Log' => APPPATH . 'classes/log.php',
    'Errorhandler' => APPPATH . 'classes/errorhandler.php',
    'PhpErrorException' => APPPATH . 'classes/errorhandler.php',
    ] );

    // Register the autoloader
    \Autoloader::register();

    \Fuel::$env = ( isset( $_SERVER['FUEL_ENV'] ) ? $_SERVER['FUEL_ENV'] : \Fuel::DEVELOPMENT );

    // Initialize the framework with the config file.
    \Fuel::init( 'config.php' );

    I overwrite the default core log class with a custom one. In dev environment things works as intended, my custom class overwrite the core one and the logs behave as they should. In production however, it doesn't. The used log class is the one defined in /core, And I can't explain why.

    Clarification : When I say in production, I mean my production server. If I set Fuel::env to production in my local dev env, it work as well.

    PHP version in local env is 7.1.4, In production server 7.0.33

    Any idea ?
  • Issue with file rights on the production server, so the class file isn't found by the webserver?
  • Shouldn't it trigger an error if it was the case ? But no anyway, rights are corrects, I checked. Other clue ?

    Thanks
  • Autoloader::init_class() does a "include", which doesn't generate an error when the file can't be loaded. It can't use a "require" because loading a file at that point is optional. You might have to debug this method to see why it doesn't load.

    And not an immediate clue, no, all our apps use an overloaded Log class...

    What is your development and production OS? What is the Fuel version used?
  • Well... If I echo a ReflexionClass getFileName method on the log class in bootstrap.php, it DOES show the path of the app Log class. Also, manually including the class works as well.

    But when I add an exit('Foo') in app/classes/log.php before the class definition, it doesn't show up... Unbelievable.

    On fuel 1.9-dev. Local env is on MacOS mojave, Production serveur on debian 8.
  • You have to be careful with Reflection that it doesn't influence the execution path. 

    Most likely, your test code triggered an autoload of the class file, and as autoloading isn't broken, it showed the correct info, as did your manual include.

    Which means the problem is that when you use the static interface of the Log class, the autoloader isn't triggered and your class isn't loaded.

    Can you add this at the top of the index.php?

    class_exist("Log", false) && die("already there?");

    If that is shown, you my have a PHP extension active on the server that introduces a Log class?
  • No, this isn't shown. And the way errors are logged on the server clearly show that the core log class is used. I checked possible differences between php.ini, apache config, and did a lot of tests, I can't explain this behavior. This is just driving me crazy right now.
  • I can imagine.

    It's been on my mind all afternoon, but I can't think of any reason why this should happen. 

    Your other overloaded classes work fine?

    You can try writing the arguments to Autoloader::load_class() to a file (without using Log), and maybe also the result of a file_exist() on the filename passed. And see if you see anything odd in there?

    Something that does come to mind now:

    Mac's file system is case-insensitve, Linux' file system is case sensitive. Fuel specs say all file names MUST be lowercase. If you class file is called "./classes/Log.php", it will not be found on Debian. 
  • Thanks for your help. No issue with uppercase tho and Yes, others extended classes works without any trouble.

    For some reasons I'm not totally sure how, but I fixed a part of the problem as now the Log class extends work as intended. But I still have another problem related to that.

    The normal behavior of Fuelphp log in case of an PhpErrorException is to pass a string containing the message, file and line to the logger. I overwrited this behavior in Errorhandler class (which is extended as well) so the full exception is passed to the Log::write function through the "logger" procedural function. (And handled differently).

    This overwrited behavior works well in local, but here again, not in the production server. In production the old string is still passed to the Log::write.

    Feeling quite unluncky with this. Extended the Fuel core several time in the past without any issue.

    EDIT : Finally found the guilty part ! The extends were working well, it was the "logger" function in core/base.php

    This method only return the Log::write() method with same parameters. But for some reasons, the Log::write called in that fonction precisely would refer to the core Log class write method, and not my extended one. Only in the production server. Duh !

    Yeah... But I would like to understand why, given that a lot of error log in the core call that function, I would like to handle those errors the new way as well.
  • HarroHarro
    Accepted Answer
    In the correct codebase, logger() calls

    \Log::write()

    which forces the load from the global namespace, and not from \Fuel\Core. 

    The first time you use a class, it will call our autoloader (assuming you have nothing special), that will check if the class is defined through add_classes(). If so, it will load that, if not, it will alias \Fuel\Core\Log to \Log.

    This means that if you have a logger() call (or a call to a \Log method) in your codebase  before the bootstrap is executed, the autoloader will alias the class as it hasn't seen your overloaded definition yet. And once aliased, the autoloader isn't triggered anymore...

    This could also be your problem?
  • Yes, that could be the problem. But still it didn't work in situations where the overloaded class should have been loaded.

    Thanks for your help anyway, as always. Cheers

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion