Make it easier to extend prepareXConditions functions

Chris D

XenForo developer
Staff member
This is a typical function you see in XenForo models and they are not very easy to extend:. This is from XenForo_Model_User:

PHP:
    public function prepareUserConditions(array $conditions, array &$fetchOptions)
    {
        $db = $this->_getDb();
        $sqlConditions = array();

        if (!empty($conditions['user_id']))
        {
            if (is_array($conditions['user_id']))
            {
                $sqlConditions[] = 'user.user_id IN(' . $db->quote($conditions['user_id']) . ')';
            }
            else
            {
                $sqlConditions[] = 'user.user_id = ' . $db->quote($conditions['user_id']);
            }
        }

The problem with extending this is if I want to pass additional $conditions to the function, it's not as easy as it could be.

The key problem, as I see it, is $sqlConditions = array();

You can't return the parent in the normal fashion because each time that resets the $sqlConditions to a blank array.

The workaround is to grab the string returned by the parent function which is the valid SQL WHERE clause and append your own clause onto that. Nowhere near ideal.

Is the solution quite simple?

What about this?

PHP:
    public function prepareUserConditions(array $conditions, array &$fetchOptions, array $sqlConditions = array())
    {
        $db = $this->_getDb();

        if (!empty($conditions['user_id']))
        {
            if (is_array($conditions['user_id']))
            {
                $sqlConditions[] = 'user.user_id IN(' . $db->quote($conditions['user_id']) . ')';
            }
            else
            {
                $sqlConditions[] = 'user.user_id = ' . $db->quote($conditions['user_id']);
            }
        }

Now we can do this:

PHP:
    public function prepareUserConditions(array $conditions, array &$fetchOptions, array $sqlConditions = array())
    {
        $db = $this->_getDb();

        if (!empty($conditions['my_condition']))
        {
            if (is_array($conditions['my_condition']))
            {
                $sqlConditions[] = 'user.my_condition IN(' . $db->quote($conditions['my_condition']) . ')';
            }
            else
            {
                $sqlConditions[] = 'user.my_condition = ' . $db->quote($conditions['my_condition']);
            }
        }

        return parent::prepareUserConditions($conditions, $fetchOptions, $sqlConditions);

Of course I may have overlooked some other solution, or a reason this may not work... but it seems like it should work to me.
 
Upvote 11
I had to extend a few of those recently, and it really pissed me off...

I ended up returning the parent with my sql conditions appended to it... Like you said, less than ideal.
 
I workaround this way

PHP:
public function prepareUserConditions(array $conditions, array &$fetchOptions)
    {
        $result = parent::prepareUserConditions($conditions, $fetchOptions);

        $sqlConditions = array($result);
   
        if (!empty($conditions['my_condition']))
        {
            // .....
        }

        if (count($sqlConditions) > 1)
        {
            return $this->getConditionsForClause($sqlConditions);
        }
        else
        {
            return $result;
        }
    }
 
Top Bottom