Yii framework pagination problem with MySQL FOUND_ROWS - php

I am trying to implement pagination in my search results with Yii. I have pagination working on my browse record pages, but for some reason, am having trouble with getting it working in search.
So far, I have the following SQL to produce the search results:
SELECT SQL_CALC_FOUND_ROWS DISTINCT user.id FROM user, personal_info WHERE (personal_info.bio LIKE '%a%' ) AND personal_info.user_id = user.id AND user.role = 'F' LIMIT 0, 8;
Which is passed to ActiveRecord as follows:
$results = $this->findAllBySql($sql);
Immediately afterwards I run this code:
$rows = $this->findBySql("SELECT FOUND_ROWS() as row_count;");
echo $rows->row_count;
Strangely, I am receiving the following error when I try and execute the above code:
Property "Search.row_count" is not defined.
For some reason, Yii is not able to retrieve the FOUND_ROWS value from MySQL.
I have pretty much exactly the same PHP code in my browse records page (but different SQL), and it works perfectly. Not sure why in this situation Yii is unable to retrieve the FOUND_ROWS value. I've tried running this code directly inside MySQL to see if there was something wrong with my SQL, but it retrieves the FOUND_ROWS value with no problems - this problem only happens when I try to do it inside Yii.
Any idea what I maybe doing wrong?
Many thanks!

Turns out that I needed to define $row_count inside the model before it would recognise it as a variable I can refer to.

Related

Duplicate query issue in yii2

I am working on one module in yii2 and please count me as a noob in this. I usually work in Laravel.
My query looks as below.
$query = SomeModel::find()
->joinWith(['relation1 s', 'relation2 r','relation3','relation4 c'])
->where(some where contions)
->where(some where contions);
The issue is in the view the yii2 debugger (Database Queries) shows "187 duplicated queries found."
My model doesn't have any loop around the query.
I have tried with removing joinWith relations but it will increase the duplicate queries to 220.
The query which gets repeated is one SELECT query
SELECT * FROM `relation4` WHERE `id`= 2159
I have checked the "relation4" model but it has nothing suspicious in it.
What should I do or where should I look to resolve this issue??

Solution Mysql Random query migrate when goto another page

I have table Post, user can search Post by find by keyword.
So, i using SQL query by like keyword and order by RAND().
When show result, i using GridView and Pagination data. And has problem, when go to another page. Example from page 1 go to page 2 with same keyword. i Will Query again and order by Rand(). So some data in page 1 can appear in page 2.
That data duplicate and not good.
So how can i solve this problem. and data query when goto page other will same with data in the first query.
I using Yii2 in my project.
Ok, I think I get it. Example MySQL query:
SELECT * FROM articles WHERE name LIKE '%tag%' LIMIT 0, 20;
Or you can use MySQL's MATCH() instead of LIKE, it doesn't matter. Then LIMIT 0, 20 is limit, how many results to show for the first page. For the second page it should be LIMIT 1, 20. This one you know I except. Then you get an array of results in the PHP, and want to get random values. PHP has such a function for you and it is called suffle().
So you just use shuffle($results); and then you can print them with foreach or whatever you use to print the data. Note that shuffle() returns boolean, so do not use $results = shuffle($results);. Hope this helps.

Get inserted ID with CakePHP without working with model

I'm trying to get the ID from an INSERT query with CAKEPHP.
In this case I'm not working with the Model itself so I'm not using the following code:
$this->ModelName->save($data);
//Then...
$this->ModelName->getInsertID();
$this->ModelName->getLastInsertID();
I'm just using
$this->query("INSERT.......");
How can I get the Inserted ID with CakePHP without referencing the model?
I think that the problem is that the query is beeing cached.
If you see the logs the query isn't even been executed (I tried your code)
try this instead
$this->query("SELECT LAST_INSERT_ID();" , false);
see manual
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-query
$this->query('SELECT LAST_INSERT_ID()');
See LAST_INSERT_ID() in the MySQL documentation.

Laravel 4 Build Query where clause on the fly

I am porting my code from CodeIgniter to Laravel. and have some question regarding the query builder.
In codeigniter, I can just add where clause to the active record object, as I initialize each property in a class like
$this->db->where('xxxx','bbbb');
in one property initialize function, and
$this->db->where('yyyy','aaaa');
in another property function, and it will all chain up until i fire off the query. But this doesn't seem to be the case of Laravel.
Here is what I do in laravel in each property initialize function
DB::table($this->table)->where('xxxx','bbbb');
DB::table($this->table)->where('yyyy','aaa');
and when a actual method is call from outside, it runs
DB:table($this->table)->get();
but this gives me a SELECT * FROM TABLENAME without anywhere clause. So what am I doing wrong here :x or I just shouldn't treat laravel same as codeigniter and think of something totally different to handle this kind of dynamic where clause?
Also in codeigniter, you can set a section of the query to cache, so even after you fire off the query , those section retains for next query, usually the where clause. Is there a similar function in Laravel? Thank you!
You can assign your current workings to a variable, and build upon that, let me show you an example based on your example:
Instead of this
DB::table($this->table)->where('xxxx','bbbb');
DB::table($this->table)->where('yyyy','aaa');
Try this...
$query = DB::table($this->table)->where('xxxx','bbbb');
$query->where('yyyy','aaa');
$results = $query->get();
I just shouldn't treat laravel same as codeigniter and think of something totally different to handle this kind of dynamic where clause?
This is not dynamic where clause.
and please, make a habit of reading the documentation.
From the docs of Fluent query builder
$users = DB::table('users')->where('votes', '>', 100)->get();
you can set a section of the query to cache, so even after you fire off the query , those section retains for next query, usually the where clause. Is there a similar function in Laravel?
$users = DB::table('users')->remember(10)->get();
Next time, just open up the docs. they contain all this.

CakePHP statement query

I have a doubt on how I should write my query on CakePHP.
Instead of using the querybuilder from CakePHP I´d like to use the statement query.
So I my query is:
SELECT `Post`.id, `Post`.title, COUNT(`Like`.id) AS `Posts_Liked`
FROM posts AS `Post`, likes AS `Like`
WHERE `Post`.id = `Like`.posts_id;
But when I send the result to the View page, I can´t get the count number when calling $post['post']['Posts_Liked'], so how should I call this data in the view?
Aggregation result will not be added to the data array as per the doc
You should either use virtual fields or get the data like this :
$post[0]['Posts_Liked']
you can inspect your data using
debug($post);
to see how your array is structured.
Using virtual fields you could achieve this like this:
$this->Post->virtualfields['Posts_liked'] = 0;
$this->Post->query('SELECT `Post`.id, `Post`.title, COUNT(`Like`.id) AS `Posts_liked` FROM posts AS `Post`, likes AS `Like` WHERE `Post`.id = `Like`.posts_id;');
and then get your data as per usual
$post['Post']['Posts_liked']
If you want it permanent, you should give a try to the counterCache
Try doing a pr($post); die(); right after making your model call, before it even gets to the view. I'm thinking it may be referenced by $post[0]['Posts_Liked'], since it's an aggregate function. You'll notice that CakePHP puts SUM(), MAX(), COUNT(), etc. in a $result[0]['count']; kind of notation. Hope this helps.
CakePHP's pr() function is much better than print_r, imho.

Categories