2

I want to extend the EE_Loader class in ExpressionEngine 2, without hacking at core EE (or CI) code.

I tried to follow the advice from Simon Emms' blog which would be a clean way to extend CI_Loader, and follows the standard convention for extending a CI class.

I've tried adding a EE_Loader.php file within codeigniter/system/core/, which is where CI_Loader (in file Loader.php) lives. My subclass_prefix is 'EE_' because I'm using ExpressionEngine so I'm confident with the filename being used, but it's not reading in the new file.

Has anyone been successful in extending ExpressionEngine's EE_Loader class? Any pointers would be appreciated.

To provide some background, I have written a PHP Session handler which writes to MySQL, using Active Record to form my queries. It will be used in a web cluster so I need to share sessions. I have considered using a NFS file, memcached, redis and MySQL solutions. MySQL is already in use, will perform well and provides a centralised store.

After reading the session data from the DB, I make another call to write to the DB, but I get a "deprecated" warning:

A PHP Error was encountered
Severity: 8192

Message: mysql_escape_string(): This function is deprecated; use mysql_real_escape_string() instead.

Filename: mysql/mysql_driver.php
Line Number: 319

I also get the same message when I use the mysqli driver.

It's happening because $this->conn_id becomes false between 2 queries. I don't know why.

  • 1
    You shouldn't extend EE_Loader in ExpressionEngine. EE is a CMS, not a framework, and isn't designed to have its internals messed around with. Perhaps you could explain what you are trying to achieve, and we could suggest a better way to do it? – Adrian Macneil Dec 11 '12 at 1:21
  • Thanks, @Adrian. I have encountered a bug in the mysql/mysqli database drivers in CI. Rather than hack these core files, I want to extend them and override the escape_str() function to fix the bug. It has been fixed in CI3 but that has not been released yet and I cannot wait for it to be released and filter through to an EE update before it's fixed. CI supports extending core classes with the 'MY_' convention and I would much rather resolve it in this way than hacking at the core files themselves. – AdamDuritz Dec 11 '12 at 7:36
  • I agree - I doubt CI3 will make it into EE anytime in the near future. However, in this case you're still probably better just avoiding the issue entirely, rather than trying to extend the EE core. What's the bug in question? – Adrian Macneil Dec 11 '12 at 11:11
  • 1
    To clarify - yes CI allows you to create MY_Loader, but EE already extends this with EE_Loader (EE is the CI app in this context). CI doesn't have any mechanism to extend an already extended class. So by trying to do that you're still pushing sh*t uphill, metaphorically speaking. – Adrian Macneil Dec 11 '12 at 11:13
  • I get a PHP warning about using a deprecated function. Tracing the code, my conn_id is closed after reading a row from the DB. The bug is mentioned here although it's for a different scenario. The fix itself, in CI3 is here. I'll amend the core file to apply a fix, knowing that it has been addressed at source, but It's against my better judgment to make hack fixes like that. – AdamDuritz Dec 11 '12 at 12:51
2

For future reference, I created a new set of DB drivers (eemysqli) which are a renamed (filenames and class names) but otherwise exact copy of codeigniter/system/database/drivers/mysqli/*. I then applied the following edit to eemysqli_driver.php:

--- drivers/mysqli/mysqli_driver.php    2012-11-26 15:19:21.000000000 +0000
+++ drivers/eemysqli/tcmysqli_driver.php        2012-12-11 19:45:45.375905181 +0000
@@ -28,7 +37,7 @@
  * @author             ExpressionEngine Dev Team
  * @link               http://codeigniter.com/user_guide/database/
  */
-class CI_DB_mysqli_driver extends CI_DB {
+class CI_DB_eemysqli_driver extends CI_DB {

        var $dbdriver = 'mysqli';

@@ -278,6 +287,8 @@
     /**
      * Escape String
      *
+     * I (AD) have amended this function to fix a known bug which is fixed in CI3.
+     *
      * @access      public
      * @param       string
      * @param       bool    whether or not the string will be used in a LIKE condition
@@ -295,18 +306,7 @@
                        return $str;
                }

-               if (function_exists('mysqli_real_escape_string') AND is_object($this->conn_id))
-               {
-                       $str = mysqli_real_escape_string($this->conn_id, $str);
-               }
-               elseif (function_exists('mysql_escape_string'))
-               {
-                       $str = mysql_escape_string($str);
-               }
-               else
-               {
-                       $str = addslashes($str);
-               }
+        $str = is_resource($this->conn_id) ? mysql_real_escape_string($str, $this->conn_id) : addslashes($str);

                // escape LIKE condition wildcards
                if ($like === TRUE)

It's a bit of a nonsense, but I can rest easy knowing I haven't hacked core EE/CI files.

0

About a year ago i made a proof of concept to integrate DataMapper ORM into ExpressionEngine.
DataMapper is a database abstraction library for CodeIgniter, that does exactly that, replace the load_class function.

It turned out that the version of CodeIgniter that ships with ExpressionEngine, does not do the check if function_exist() before loading most or any of the core functions. It took only a very small modification to the core to be able to override the load_class function. It boils down to wrapping the load_class function in a if not function_exists conditional.

# 1. file: /system/codeigniter/system/core/Common.php
if ( ! function_exists('load_class'))
{
    function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
    {
    ...
    }
}

This allows us to load our own bootstrap first from the main index.php file, just before the core system bootstrap would have been loaded.

# 2. file: /index.php at the, just before loading the bootstrap file
require_once APPPATH.'third_party/datamapper/bootstrap.php';

NOTES

  1. the code can be found on https://github.com/GDmac/EE_DataMapper/

  2. The naming can be a bit confusing.
    A). The CodeIgniter ActiveRecord class actually is a QueryBuilder, and in CodeIgniter 3 it correctly has been renamed to QueryBuilder.
    B). Datamapper ORM ( http://datamapper.wanwizard.eu ) actually
    follows the ActiveRecord design pattern.
    C). DataMapping is another design pattern, which abstracts the database away from the rest of the code

  3. general tip: Avoid hacking core with lots of your own code intermingled in the core. Instead just add/insert an extra hook in the core and put our actual code into an extension.
    This goes even for third-party add-ons.
    See: http://madebyhippo.com/blog/view/expressionengine_hook_dont_hack

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.