Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
ORM side effects
  • My application has a base controller that most other classes extend. It is responsible for site-wide tasks such as authentication and building the user model. It uses a few different data models that all extend the ORM.

    One of the fields in the user model is called "categories". It's a multi-dimensional array that stores a few arrays of integers (strings really, but you know...we're weakly typed), as well as an HTML string. It looks a little something like this:

    array (size=4)
      'corporate' => string '99' (length=2)
      'all' => 
        array (size=4)
          0 => string '99' (length=2)
          1 => string '99' (length=2)
          2 => string '101' (length=3)
          3 => string '102' (length=3)
      'below' => 
        array (size=3)
          0 => string '99' (length=2)
          1 => string '101' (length=3)
          2 => string '102' (length=3)
      'option_list' => string '<optgroup label="League"><option value="99">NFL</option></optgroup><optgroup label="&nbsp;Conference"><option value="101">&nbsp;AFC</option><option value="102">&nbsp;NFC</option></optgroup>'

    I make the user model accessible to my views by setting it as a global variable, like this:

    \View::set_global('current_user', $this->current_user, false);

    Notice that I'm passing "false" to the set_global() method, to disable encoding. I use the "option_list" value to populate a few different select lists around the application.

    A recent feature request requires that search data persist between HTTP requests. In the course of modifying a single query, my user model is being affected, but I don't know why. Specifically, the "option_list" is getting encoded. In other words, my "categories" array suddenly looks like this:

    array (size=4)
      'corporate' => string '99' (length=2)
      'all' => 
        array (size=4)
          0 => string '99' (length=2)
          1 => string '99' (length=2)
          2 => string '101' (length=3)
          3 => string '102' (length=3)
      'below' => 
        array (size=3)
          0 => string '99' (length=2)
          1 => string '101' (length=3)
          2 => string '102' (length=3)
      'option_list' => string '&lt;optgroup label=&quot;League&quot;&gt;&lt;option value=&quot;99&quot;&gt;NFL&lt;\/option&gt;&lt;\/optgroup&gt;\n&lt;optgroup label=&quot;&nbsp;Conference&quot;&gt;&lt;option value=&quot;101&quot;&gt;&nbsp;AFC&lt;\/option&gt;&lt;option value=&quot;102&quot;&gt;&nbsp;NFC&lt;\/option&gt;'

    My "keyword" filter used to look like this:

            if (strlen(\Input::post('keyword')) > 0)
            {
                $keyword = '%' . \Input::post('keyword') . '%';
                $query->related('customer')
                    ->related('current_rep')
                    ->related('location')
                    ->and_where_open()
                        ->where('customer.name', 'LIKE', $keyword)
                        ->or_where('customer.email', 'LIKE', $keyword)
                        ->or_where('location.address', 'LIKE', $keyword)
                        ->or_where('current_rep.username', 'LIKE', $keyword)
                        ->or_where('current_rep.profile_fields', 'LIKE', $keyword)
                    ->and_where_close();
            }

    Now it looks like this:

            $keyword = \Input::post('keyword', \Session::get('keyword', false));
            \Session::set('keyword', $keyword);
            
            if ($keyword)
            {
                $keyword = '%' . $keyword . '%';
                $query->related('customer')
                    ->related('current_rep')
                    ->related('location')
                    ->and_where_open()
                        ->where('customer.name', 'LIKE', $keyword)
                        ->or_where('customer.email', 'LIKE', $keyword)
                        ->or_where('location.address', 'LIKE', $keyword)
                        ->or_where('current_rep.username', 'LIKE', $keyword)
                        ->or_where('current_rep.profile_fields', 'LIKE', $keyword)
                    ->and_where_close();
            }

    I did make other changes to the controller besides this, but by commenting out code I was able to determine that this specific piece of code is the one that is causing the issue.

    Digging deeper I found that if I comment out the lines specifically related to the "current_rep", the encoding issue disappears.

    I realize that the ORM automatically caches query results. Is it also modifying my existing query data in this case? How can I prevent the encoding from taking place, and why wasn't this issue occurring with the alternate code above? Does it have anything to do with sessions?
  • Corretion to my n00bery:

    The issues was NOT introduced by the code change. The issue existed before, I just didn't realize it. So, the issue is completely unrelated to the code change mentioned above. I do believe it has something to do with the ORM caching.
  • More info on the database structure:

    Users table (the current_rep model uses this table)
    +----------------+--------------+------+-----+---------+----------------+
    | Field          | Type         | Null | Key | Default | Extra          |
    +----------------+--------------+------+-----+---------+----------------+
    | id             | int(11)      | NO   | PRI | NULL    | auto_increment |
    | username       | varchar(255) | YES  | MUL | NULL    |                |
    | password       | varchar(255) | NO   |     | NULL    |                |
    | group          | int(11)      | NO   |     | 1       |                |
    | email          | varchar(255) | NO   |     | NULL    |                |
    | last_login     | varchar(25)  | NO   |     | NULL    |                |
    | login_hash     | varchar(255) | NO   |     | NULL    |                |
    | profile_fields | text         | NO   |     | NULL    |                |
    | email_verified | tinyint(1)   | NO   |     | 0       |                |
    | created_at     | int(11)      | NO   |     | 0       |                |
    | updated_at     | int(11)      | NO   |     | 0       |                |
    | client_id      | int(11)      | NO   |     | NULL    |                |
    | category_id    | int(11)      | NO   |     | NULL    |                |
    | calendar_id    | int(11)      | YES  |     | NULL    |                |
    +----------------+--------------+------+-----+---------+----------------+


    Categories table
    +------------+--------------+------+-----+---------+----------------+
    | Field      | Type         | Null | Key | Default | Extra          |
    +------------+--------------+------+-----+---------+----------------+
    | id         | int(11)      | NO   | PRI | NULL    | auto_increment |
    | name       | varchar(255) | NO   |     | NULL    |                |
    | client_id  | int(11)      | NO   |     | NULL    |                |
    | parent_id  | int(11)      | NO   |     | NULL    |                |
    | lft        | int(11)      | NO   |     | NULL    |                |
    | rgt        | int(11)      | NO   |     | NULL    |                |
    | created_at | int(11)      | NO   |     | NULL    |                |
    | updated_at | int(11)      | NO   |     | NULL    |                |
    | group      | varchar(10)  | NO   |     | NULL    |                |
    | address    | varchar(255) | NO   |     | NULL    |                |
    | phone      | varchar(15)  | NO   |     | NULL    |                |
    | timezone   | varchar(32)  | NO   |     | NULL    |                |
    +------------+--------------+------+-----+---------+----------------+

  • HarroHarro
    Accepted Answer
    There is only one place in the framework that runs htmlentities, which is the View.

    Since this is an object, all variables containing this object are actually references to the same object. So if one changes, they all change.

    So you need to check if it isn't passed to a View somewhere (perhaps as a related object of another object?) and being encoded.

Howdy, Stranger!

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

In this Discussion