phpfunctioncakephpoverridinglate-static-binding

Override some function cakephp (Late Static Bindings )


I use CakePHP 2.9.8 to develop an old application that was written 7 years ago and developed until now. unfortunately the first developer add some codes in CakePHP's library and for migrating to the 3th version of CakePHP I need to transfer the changing in the application.

one of the changing is in the App::load located in ~\lib\Cake\Core\App.php and as it used static::_map($file, $className, $plugin);, I can write a class which extend App.php and rewrite the _map function.

My questions:

  1. Can be override a protected function or property? if no:

  2. why in CakePHP they were used (or called) like static:: for example: static::_map($file, $className, $plugin); but the definition is protected static function _map($file, $name, $plugin = null) if yes:

  3. Where in my application should I define class Foo which extend App and for load function that I want to remove the developer changes, where should I write Foo::load?.

I put also App::load function here:

public static function load($className) {
    if (!isset(static::$_classMap[$className])) {
        return false;
    }
    if (strpos($className, '..') !== false) {
        return false;
    }

    $parts = explode('.', static::$_classMap[$className], 2);
    list($plugin, $package) = count($parts) > 1 ? $parts : array(null, current($parts));

    $file = static::_mapped($className, $plugin);
    if ($file) {
        return include $file;
    }
    $paths = static::path($package, $plugin);

    if (empty($plugin)) {
        $appLibs = empty(static::$_packages['Lib']) ? APPLIBS : current(static::$_packages['Lib']);
        $paths[] = $appLibs . $package . DS;
        $paths[] = APP . $package . DS;
        $paths[] = CAKE . $package . DS;
    } else {
        $pluginPath = CakePlugin::path($plugin);
        $paths[] = $pluginPath . 'Lib' . DS . $package . DS;
        $paths[] = $pluginPath . $package . DS;
    }

    $normalizedClassName = str_replace('\\', DS, $className);

    // Start point of custom codes
    // Load Custom Classes that are usually added during customizations
    // This part is for accepting a class like **XControllerCustom** but the name of file is: **XController**
    if($package === 'Model'){
        foreach ($paths as $path) {
            $file = $path . DS . $className . '.php';
            $file_custom = $path . 'Custom' . DS . $normalizedClassName . '.php';
            if (file_exists($file_custom) && file_exists($file)) {
                self::_map($file_custom, $className);
                include $file;
                return include $file_custom;
            }
        }
    }
    // End of custom's code     

    foreach ($paths as $path) {
        $file = $path . $normalizedClassName . '.php';
        if (file_exists($file)) {
            static::_map($file, $className, $plugin);
            return include $file;
        }
    }

    return false;
}

Solution

  • You have some serious lack of knowledge in OOP in php. Read these links carefully, they'll give you the answers and hopefully a complete understandig of both topics.

    1. http://php.net/manual/en/language.oop5.visibility.php
    2. http://php.net/manual/en/language.oop5.late-static-bindings.php

    Also there are plenty of questions and answers related to both on SO. Just search for them if the manual is not sufficient.


    For number three, there is no fixed place. Just put it in a Lib or Utility folder inside your app. However, I would choose an autoloader over the built in App stuff and just use uses to make my classes available. If your app doesn't use composer yet, just add it and use its autoader and namespaces. The only reason 2.x is still not using them is backward compatibility. App is a crutch to get namespace like functionality done without actually using them.