2

I'm developing an API REST application with Yii2 and I have this query problem:

I receive a get request by url with two params like this:

http://localhost/yii2/rest/web/index.php/v1/functions/search?name=test&code=int

I would like to treat the get params with an Or condition in my SQL query, instead of an And condition.

I know that using this way it works:

$provider = new ActiveDataProvider([
    'query' => $model->find()->select('idFunction')->where(['or',['name'=>'test'],['code'=>'int']]),
    'pagination' => false
]);

But this way doesn't work. It behaves as an And condition:

$provider = new ActiveDataProvider([
    'query' => $model->find()->select('idFunction')->where(['or',$params]),
    'pagination' => false
]);

I think it has to do the way the variable $params is converted.

Here is my entire code:

public function actionSearch()
{
    $params = \Yii::$app->request->queryParams;
    exit(print_r($params));
    if (!empty($params)) {
        $model = new $this->modelClass;
        foreach ($params as $key => $value) {
            if (!$model->hasAttribute($key)) {
                throw new \yii\web\HttpException(404, 'Invalid attribute:' . $key);
            }
        }
        try {
            $provider = new ActiveDataProvider([
                    'query' => $model->find()->select('idFunction')->where(['or',$params]),

                'pagination' => false
            ]);
        } catch (Exception $ex) {
            throw new \yii\web\HttpException(500, 'Internal server error');
        }

        if ($provider->getCount() <= 0) {
            throw new \yii\web\HttpException(404, 'No entries found with this query string');
        } else {
            return $provider;
        }
    } else {
        throw new \yii\web\HttpException(400, 'There are no query string');
    }
}    
6
  • I would guess that the problem is that you are passing all the parameters in an array as the second element of the array that has the or, basically doing allThis or null so it works as an and. Did you try making the first element an or? Something like this: $model->find()->where(array_unshift($params, 'or'))? You could give that a try and check the generated SQL on the debugger. Commented Nov 25, 2020 at 20:14
  • Tks for your response @RaulSauco. I've tried your recommendation and now it brings me all ids values from the table. How could check the generated SQL on the debugger? Commented Nov 25, 2020 at 20:33
  • If you have the debugger configured, YII_DEBUG is true, and your IP is on the allowed list, i.e. you are on the same machine as the server, you should be seing the debug bar at the bottom of the page. You can also access the page at the localhost/mypage/debug endpoint. Commented Nov 25, 2020 at 20:37
  • They probably won't see the debug bar when testing REST requests. But, there should be link to debugger page for specific request in response headers. Commented Nov 26, 2020 at 15:35
  • @RaulSauco thanks! I've reached the debuger page, but, as Michal Hynčica said, I couldn't go further than a requests status list. I guess is because i'm trying testing request REST Commented Nov 29, 2020 at 14:14

1 Answer 1

1

You can iterate over the parameter array to modify it.

Using array_unshift($conditions, 'or') like I suggested on the comments does not work. The method expects an array where each element, except the operand itself, is itself, an array with only one element.

Yii2 operator format docs

Something that works, I just tried, but it isn't very pretty, is to iterate over the elements and return an array of the expected form.

$orQuery = ['or'];
foreach ($params as $key => $value) {
   $orQuery[] = [$key => $value];
}
$query->where($orQuery);

This returns the array that the query() method expects.

['or', ['name1' => 'value1'], ['name2' => 'value2'], ...]

That produces the SQL:

SELECT * FROM table WHERE ('name1'='value1') OR ('name2'='value2')...;
Sign up to request clarification or add additional context in comments.

2 Comments

@4aLifeTime Great to hear that it worked. Don't forget to mark the answer as accepted and/or vote it up.
Yes, I just did it. As i'm new at stackoverflow i can't vote yet and after your comment i've realized i can mark answers as accepted, so i did it. Thanks again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.