I'd like to traverse a resultset using a while() loop instead the most common foreach()
If I have this code for example:
$articles = $this->Articles->find();
foreach ($articles as $article) {
echo $article->name;
}
How can I access rows of $articles using a while loop ?
I already tried traverse it using next() or $articles->next() with no success.
I'm not sure that you really need to use a while() loop for what you're trying to achieve, but to answer the question, you have to first get the result set, and then use its Iterator::valid() implementation for the loop condition, this is where the current result is being fetched, which you can then access via current(). Advancing the cursor is then being done using next().
$query = $this->Articles->find();
$resultSet = $query->all();
while ($resultSet->valid()) {
$article = $resultSet->current();
// ...
$resultSet->next();
}
See also API > \Cake\ORM\ResultSet
Related
Inside a cell I need to access the TreeOptions model.
So I've wrote this :
$this->loadModel( 'TreeOptions' );
$i = $this->TreeOptions->find( 'all' );
But when I do the foreach like this :
foreach( $i as $row )
debug( $row->description );
It only returns the last record of the result.
The only way I've found to make it work as desired is adding the limit clause :
$i = $this->TreeOptions->find( 'all', [ 'limit' => 200 ] );
And then, I can get the whole set of records.
What am I missing ?
Thanks.
Regards.
In your first snippet, the variable $i, is a state where the query has not yet run. See the excerpt from CakePHP 3 Cookbook: Retrieving Data & Results — Using Finders to Load Data:
// Find all the articles.
// At this point the query has not run.
$query = $articles->find('all');
// Iteration will execute the query.
foreach ($query as $row) {
}
// Calling all() will execute the query
// and return the result set.
$results = $query->all();
// Once we have a result set we can get all the rows
$data = $results->toArray();
// Converting the query to an array will execute it.
$results = $query->toArray();
I use the Wordpress function $wpdb->get_results()
https://codex.wordpress.org/Class_Reference/wpdb#SELECT_Generic_Results
It says:
"If no matching rows are found, or if there is a database error, the return value will be an empty array."
Then how can I know if the query failed OR if it's empty?
Use
$results=$wpdb->get_results($yoursql);
if (count($results)> 0){
//do here
}
But if you want to know if query failed
$wpdb -> show_errors ();
$wpdb -> get_results ($wpdb -> prepare($sql));
$wpdb -> print_error ();
Bit late to the party here but I'm just looking for the same thing. I've had a browse through the wp-db.php code on version 4.4.2.
On line 1422, inside the method flush() there's a bit of code which resets the last_error property:
$this->last_error = '';
This flush() method is called in the query() method on line 1693:
$this->flush();
The get_results() method calls query() on line 2322:
if ( $query ) {
$this->query( $query );
} else {
return null;
}
With this we can be pretty sure that more or less every time get_results() (Or get_row() too for that matter) is called, query() and flush() are both called, which ensures that last_error is set to the empty string before the query is executed.
So assuming the query runs (If it doesn't, null is returned - if the query is empty for example), last_error should contain an error message if the query was to fail for some reason.
Since last_error is flush()ed/reset each time, it should only contain an error for the last query that was run, rather than the last error for any query that had been run previously. With this in mind it should be safe to rely on last_error to determine whether something went wrong with the query.
$results = $wpdb->get_results($sql);
if (is_null($results) || !empty($wpdb->last_error)) {
// Query was empty or a database error occurred
} else {
// Query succeeded. $results could be an empty array here
}
Not the most intuitive in my opinion, but it seems to be sufficient.
Personally, I've written my own class around wpdb for my own benefit. This is my getResults() method.
public function getResults($query, $bindings = [])
{
// Prepare the statement (My prepare method inspects $query and just returns it if there's no bindings, otherwise it uses $wpdb->prepare()
$prepared = $this->prepare($query, $bindings);
// Execute the statement
$rows = $this->db->get_results($prepared, ARRAY_A);
// If an array was returned and no errors occurred, return the result set
if (is_array($rows) && empty($this->db->last_error)) {
return $rows;
}
// On failure, return false
return false;
}
Hope this helps.
Wpdb->get_results function from wordpress returns the result if successful otherwise it will return null. There can be many reasons if a query get failed.Refer in-depth article on debugging get_results() returning empty results here
Although you can use functions like wpdb->show_error() to check what was the last error after executing the sql query. sometimes this error returns empty
then try to use wpdb->last_query to check the final query that get formed.
Currently I have an array sort. Sort has only one key / value. The keys and values are always different. This array always has just 1 key/value pair. How do I access both elements dynamically in laravel?
I have already solved this but think it is extremely inefficient.
my current solution
I made a function orderQuery() to return the key name.
function orderQuery() {
foreach (Input::get('sort') as $key => $value) {
return $key; // there is only 1 item in the array but this looks like bad practice
}
}
Then I call it like this to respond to my request
->orderBy(orderQuery(), Input::get('sort.'.orderQuery()))
Is there a better way to do this?
You can use key()
$key = key(Input::get('sort'));
If you want to be save reset the pointer first:
$sort = Input::get('sort');
reset($sort);
$key = key($sort);
How can I loop trough my db results in the controller by using a foreach loop?
$select = new Select();
$select->from('table_name');
$select->where(array('salt' => $salt));
$select->where(array('ip' => $this->_getUserIp()));
$rowset = $this->tableGateway->selectWith($select);
return $rowset;
I guess I need to convert the db result object to an array?
Thanks in advance
http://framework.zend.com/manual/2.1/en/modules/zend.db.result-set.html
Zend\Db\ResultSet\ResultSet extends traversable and therefore you can use foreach on it.
foreach($this->getSomeTable()->fetchAll() as $row) {
//here you can access the row as an array or use getters if you have set a prototype object
//eg
$userId = $row['user_id'];
$userId = $row->user_id;
$userId = $row->getId();
}
Also, I suggest reading through the getting started guide. All this basic stuff is explained there.
http://framework.zend.com/manual/2.1/en/user-guide/overview.html
I have I problem that I hope someone can help me with. I thought this code was right, but it will not work. Below is my code, it is a function for my CakePHP 2.2.2 site, the main aim of the code is to produce a menu system from database results. The problem is with my foreach loop, it will not loop. All $Key does is return the value of 2 (three records within the table at this time). So When I display / echo / debug $Menu, the only result I get is the last result stored within the database.
I know the SQL command is right, if that is debuged / echoed then all three results are displayed. The idea of this loop was to get it to count the results, so that I could run a check on a selected field. Where I am going wrong?
function MenuSystem() {
$this->loadModel('Menu');
$MenuSQL = $this->Menu->find('all', array('conditions' => array('active' => true)));
foreach ($MenuSQL as $Key=>$Value) {
$MenuSystem = $MenuSQL[$Key];
$this->Menu = $MenuSystem;
}
}
Many Thanks,
Glenn.
UPDATE :::
Below is my function, now my foreach loop now works, don't know what I was doing wrong, but I know think its working. You can see the print_r command that I am using for testing, if I use that, then all links from my database are printed / echoed on the screen and all works. But if I try and call the $this->Menu from another controller, then only the last record is echoed on the screen. I have moved the $this->Menu outside of the foreach loop, but it made no difference, with it inside the loop or outside, it still only echoes the last record and not all three. So what I am doing wrong?
function MenuSystem() {
$this->loadModel('Menu');
$SiteBase = '/projects/cake/';
$MenuSQL = $this->Menu->find('all', array('conditions' => array('active' => true)));
foreach ($MenuSQL as $key => $Value) {
$MenuAccessLevel = $MenuSQL[$key]['Menu']['roles_id'];
if ($MenuAccessLevel == 1) {
$Path = $MenuSQL[$key]['Menu']['path'];
$Title = $MenuSQL[$key]['Menu']['title'];
$MenuSys = "<a href=\" " . $SiteBase . $Path . " \">" . $Title ."";
} else {
print ("Admin");
}
//print_r($MenuSys);
} //End of Foreach Loop
$this->Menu = $MenuSys;
} //End of function MenuSystem
So When I display / echo / debug $Menu, the only result I get is the last result stored within the database.
You're setting the value of $this->Menu within the foreach, so when the foreach is complete it will take the last value iterated over.
If you want to find the number of records matching a condition, try:
$menuCount = $this->Menu->find('count', array(
'conditions'=>array('active'=>true)
));
$this->set(compact('menuCount'));
Edit: also, by setting the value of $this->Menu within the foreach, you're overwriting the Menu model variable. This is not a good idea.
Edit2: to get the counts of rows as grouped by some value, try:
$this->Menu->virtualFields = array('count' => 'count(*)');
$counts = $this->Menu->find('all', array(
'group'=>'Role',
'fields'=>array('Role', 'count'),
));
This generates SQL to have the results grouped by the Role column. Returned fields are the name of the role, and the number of rows having that value.
If you wanted to do it with a foreach loop instead, it might look like:
$menus = $this->Menu->find('all', array('fields'=>array('id', 'Role')));
$counts = array('user'=>0, 'admin'=>0);
foreach ($menus as $menu) {
$role = $menu['Menu']['Role'];
$counts[$role] += 1;
}