Having troubles with mysqli::fetch_object(); - php

after reading like 5 hours on Google I can't fix something with MySQLI.
I spent all my life programming in MySQL, and now I am trying to update my knowledge using mysqli but I have some troubles.
I have a little function called news_Default() like this:
<?php
Class Test extends DB{
public function news_Default(){
$query = $this->db->query('SELECT * FROM news');
if($query->num_rows == 0)
return false;
else
return $query->fetch_object();
}
}
?>
And I used in this way:
<?php
while($new = $panel->news_Default()){
print_r($new);
}
?>
In MySQL, when I return the object, I can use it with 'while' or 'foreach' loop without problems, but the real problem is here, with mysqli.
When I used the 'while' (second codeblock), it loops 6,000 times (I used a $counter++ to test it), and when I used foreach, it loops exactly 7 times. In my table called 'news' I have only two records. So, how can I return the object and use it outside without having this problems? Because when I use it inside the class like $new = $query->fetch_object() works perfect.

You are doing sql query every time when you are calling news_Default.
Examle for fixing it.
Class Test extends DB{
private $_cached_news = null; // let's store our query result
public function news_Default(){
if ($this->_cached_news === null){ // not stored?
$this->_cached_news = $this->db->query('SELECT * FROM news');} // let's query
$return = $query->fetch_object(); // get next object
if (!$return) // there is no objects anymore?
$this->_cached_news = null; // let's clear our result
return $return;
}
}

Related

Select in function for use outside of function

I'd like to select entries inside of a function and use the results in a while statement outside of the function.
This is what I have...
public function getPractices($dbh) {
$practices = $dbh->prepare("SELECT * FROM `practices`");
$practices->execute();
return $practices;
}
I would like to then do something like...
$practices = new SomethingDumbthing;
$practices->getPractices($dbh);
while ($row = $practices->fetch(PDO::FETCH_ASSOC)) {
Do stuff
}
While messing around, I got it to partially work, except for the fact that it was looping over the same row.
Any pointers?
In your example, you never actually use the statement.
$practices = new Class;
// this returns an object, but you don't save it to anything!
// try $data = $practices->getPractices($dbh);
$practices->getPractices($dbh);
// so now, you are calling fetch on your class, not on the database results!
while ($row = $practices->fetch(PDO::FETCH_ASSOC)) {
Do stuff
}

This result is a forward only result set, calling rewind() after moving forward is not supported - Zend

In Zend app, I use Zend\Db\TableGateway and Zend\Db\Sql to retrieve data data from MySQL database as below.
Model -
public function getCandidateEduQualifications($id)
{
$id = (int) $id;
$rowset = $this->tableGateway->select(function (Sql\Select $select) use ($id)
{
$select->where
->AND->NEST->equalTo('candidate_id', $id)
->AND->equalTo('qualification_category', 'Educational');
});
return $rowset;
}
View -
I just iterate $rowset and echo in view. But it gives error when try to echo two or more times. Single iteration works.
This result is a forward only result set, calling rewind() after
moving forward is not supported
I can solve it by loading it to another array in view. But is it the best way ? Is there any other way to handle this ?
$records = array();
foreach ($edu_qualifications as $result) {
$records[] = $result;
}
EDIT -
$resultSet->buffer(); solved the problem.
You receive this Exception because this is expected behavior. Zend uses PDO to obtain its Zend\Db\ResultSet\Resultset which is returned by Zend\Db\TableGateway\TableGateway. PDO result sets use a forward-only cursor by default, meaning you can only loop through the set once.
For more information about cursors check Wikipedia and this article.
As the Zend\Db\ResultSet\Resultset implements the PHP Iterator you can extract an array of the set using the Zend\Db\ResultSet\Resultset:toArray() method or using the iterator_to_array() function. Do be careful though about using this function on potentially large datasets! One of the best things about cursors is precisely that they avoid bringing in everything in one go, in case the data set is too large, so there are times when you won't want to put it all into an array at once.
Sure, It looks like when we use Mysql and want to iterate $resultSet, this error will happen, b/c Mysqli only does
forward-moving result sets (Refer to this post: ZF2 DB Result position forwarded?)
I came across this problem too. But when add following line, it solved:
$resultSet->buffer();
but in this mentioned post, it suggest use following line. I just wonder why, and what's difference of them:
$resultSet->getDataSource()->buffer();
This worked for me.
public function fetchAll()
{
$select = $this->tableGateway->getSql()->select();
$resultSet = $this->tableGateway->selectWith($select);
$resultSet->buffer();
$resultSet->next();
return $resultSet;
}
$sql = new Zend\Db\Sql($your_adapter);
$select = $sql->select('your_table_name');
$statement = $sql->prepareStatementForSqlObject($select);
$results = $statement->execute();
$resultSet = new ResultSet();
$resultSet->initialize($results);
$result = $resultSet->toArray();

Writing SQL Queries in Codeigniter 2.0

I have the following function that does not work and I'm having the hardest time trying to figure it out. I'm 12 and just learning, so forgive me:
function get_answer() {
$answer = $this->db->query("SELECT COUNT(questions) FROM possible_quest WHERE questions='something'");
return $answer;
}
When I run the following SQL query in phpmyadmin, it returns the expected result
SELECT COUNT(questions) FROM possible_quest WHERE questions='something'
How do I get this working in CodeIgniter using my function above?
The PHP error I get is
A PHP Error was encountered
Severity: 4096
Message: Object of class CI_DB_mysql_result could not be converted to string
Could be:
function get_answer()
{
$query = $this->db->query("SELECT COUNT(questions) AS count FROM possible_quest WHERE questions='something'");
$count = $query->row(); // returns an object of the first row
return $count->count;
// OR
$count = $query->row_array(); // returns an asociative array of the result
return $count['count'];
}
Another thing: if you want to pass 'something' as a variable, you can use parametrized query, like
$sql = "SELECT COUNT(questions) AS count FROM possible_quest WHERE questions = ?";
$query = $this->db->query($sql, array($something));
which has the benefit of escaping automatically your variable, so you don't worry about sql injections.
You need to setup to the count.
Heres what you need to do is
$answer = $this->db->query("SELECT COUNT(questions) as count FROM possible_quest WHERE questions='something'")->first_row()->count;
//$answer is now setup to be count
One line. Thats the beauty of CI
You're getting that error because
return $answer;
should be
return $answer->result();
The error you are getting is related to the fact that $this->db->query returns a result object, so you cannot use $answer directly as a string.
I suggest that you use print_r($answer) to see what could be going wrong with your conversion of objects to strings, if you have such a function in your model.
CodeIgniter has functions for building queries and returning the count:
function get_answer() {
$this->db->from("possible_quest");
$this->db->where("questions", "something");
return $this->db->count_all_results();
}
NOTE: The name of the function 'get_answer' doesn't match what you're actually doing. It looks like you're getting a count of questions, not an answer, so you should name it to something that makes more sense, like 'get_question_count'.
I recommend you to use an Active Record with method chaining when possible:
public function getAnswer() {
return
$this->db->
select('id')->
where('questions', 'something')->
get('possible_quest')->row()->count
;
}
or
public function getAnswer() {
return
$this->db->
select('id')->
from('possible_quest')->
where('questions', 'something')->
get()->row()->count
;
}
It's secure, easy to use, easy to understand and read. Don't listen to people saying that a single-line code is something good because a good code should be readable.

Is it possible to call a PHP function from an SQL query?

Say there is a special PHP function foo($number) that returns double the value of its input. Further, say there is a table that contains the column "number." Is there a way to have the PHP function and SQL query to run together so that I would get the following:
Number | Double
================
1 | 2
5 | 10
While in this simple example column Double can easily be implemented within the SQL statement, answers should cover the more general case of calling any PHP function, as there are many operations that are difficult to impossible in SQL but easy in PHP.
No, since the query results come straight from MySQL. You can apply the function to the result set after you execute your query, either by using a loop or by applying your function to the results using array_map() function.
Depending on what you're actually trying to achieve it might be possible to decouple the data source and the consumer a bit, enough to put another component between them.
Let's start with
<?php
$result = getData($pdo); // a)
doSomething($result); // b)
function getData($mysql) {
return mysql_query('SELECT x FROM soTest', $mysql);
}
function doSomething($result) {
while ( false!==($row=mysql_fetch_assoc($result)) ) {
echo ' ', join(', ', $row), "\n";
}
echo "----\n";
}
There's very little you can do to alter a mysql result resource. And doSomething() does nothing more than iterating over the result set. It does nothing that is special to a mysql result set, yet it allows nothing else but this exact resource type by using mysql_fetch_xyz().
Let's try this again using PDO (PDO_MYSQL).
$result = getData($pdo);
doSomething($result);
function getData($pdo) {
return $pdo->query('SELECT x FROM soTest');
}
function doSomething(PDOStatement $result) {
while ( $row=$result->fetch(PDO::FETCH_ASSOC) ) {
echo ' ', join(', ', $row), "\n";
}
echo "----\n";
}
That didn't change much. Some names but essentially this is the same. But PDOStatement implements the Traversable interface, so you can use it directly with foreach.
$result = getData($pdo);
doSomething($result);
function getData($pdo) {
return $pdo->query('SELECT x FROM soTest', PDO::FETCH_ASSOC);
}
function doSomething($traversable) {
foreach( $traversable as $row ) {
echo ' ', join(', ', $row), "\n";
}
echo "----\n";
}
That's a game changer... We can pass any traversable/iterator to doSomething() and it still does more or less the same thing as before.
Now we can put something "between" getData() and doSomething(). This something takes an inner iterator (like getData() provides in the form of an PDOStatement) and behaves itself like an iterator (so DoSomething() can use it) returning all elements of its inner iterator but modifying some elements.
I chose to extend FilterIterator for this example for no particular reason. You need php 5.3+ to run this demo since it uses an anonymous function:
<?php
$pdo = initDemo();
echo "#1: passing \$result\n";
$result = getData($pdo); // a)
doSomething($result); // b)
echo "#2: passing ModifyIterator\n";
$result = getData($pdo); // exact same as a)
$result = new ModifyIterator($result, null, function($e) {
$e['y'] = '/' . ($e['x'] * 2) .'/';
return $e;
});
doSomething($result); // exact same as b)
function getData($pdo) {
return $pdo->query('SELECT x FROM soTest', PDO::FETCH_ASSOC);
}
function doSomething($traversable) {
foreach($traversable as $row) {
echo ' ', join(', ', $row), "\n";
}
echo "----\n";
}
class ModifyIterator extends FilterIterator {
protected $fnAccept, $fnModify;
public function __construct($it, $fnAccept, $fnModify) {
// todo: test parameters!
$this->fnAccept = $fnAccept;
$this->fnModify = $fnModify;
if ( !($it instanceof Iterator) ) {
$it = new IteratorIterator($it);
}
parent::__construct($it);
}
public function accept() {
return $this->fnAccept ? $this->fnAccept(parent::current()) : true;
}
public function current() {
if ( $this->fnModify ) {
$fn = $this->fnModify;
return $fn(parent::current());
}
return parent::current();
}
}
function initDemo() {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'localonly', 'localonly');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('CREATE TEMPORARY TABLE soTest (x int auto_increment, primary key(x))');
$pdo->exec('INSERT INTO soTest VALUES (),(),(),(),()');
return $pdo;
}
prints
#1: passing $result
1
2
3
4
5
----
#2: passing ModifyIterator
1, /2/
2, /4/
3, /6/
4, /8/
5, /10/
----
The important part is that ModifyIterator forces very little particular behaviour on the inner iterator (e.g. you can still use an unbuffered query without the need to transfer all the data into the php process' memory at once) and that both getData() and doSomething() are left unchanged.
One way would be to fetch the results into objects:
class NumberDoubler
{
public $number;
public function __construct()
{
$this->number *= 2;
}
}
$pdo = new PDO('mysql:host=localhost;dbname=db_name', 'uname', 'pword');
$stmnt = $pdo->query('SELECT number FROM db_table');
$result = $stmnt->fetchAll(PDO::FETCH_CLASS, 'NumberDoubler');
print_r($result);
The result will be an array of objects with '$number' doubled. Of course, iteration will still be done "behind the scenes", and the manual warns, "Using this method to fetch large result sets will result in a heavy demand on system and possibly network resources."
See also PDOStatement::setFetchMode().
You don't need to use PHP. You can just execute a regular SQL statement as follows.
SELECT number, number * 2 FROM tablename;
//Your query would prob be like so.
$query = mysql_query("SELECT (number * 2) as double,number FROM table");
echo '<table>';
while($row = mysql_fetch_assoc($query))
{
echo sprintf('<tr><td>%d</td><td>%d</td></tr>',$row['number'],$row['double']);
}
echo '</table>';
I think I understand your question.
It sounds as though you want to pull a number from a database and double it through a php function.
I would first learn to write the php function... Check this out for a tutorial.
Once you have that down, pull your number from the database. Here is a tutorial on how to do that.
This is all about learning. Me posting code for you to just copy doesn't help you learn and is basically a waste of my time. Best of luck.
It depends on what the function is doing. Basic stuff like arithmetic can be done with SQL directly. Otherwise, you can loop over the result array and run the function in the particular field, e.g.:
$rows = array();
foreach(($row = mysql_fetch_assoc($result))) {
$row['double'] = func($row['number']);
rows[] = $row;
}
No, it's impossible to use php function() and sql together
However, you can get results from SQL database and apply whatever PHP function on it

PHP mySQL - Can you return an associated array with a number index?

I have this method in my db class
public function query($queryString)
{
if (!$this->_connected) $this->_connectToDb(); //connect to database
$results = mysql_query($queryString, $this->_dbLink) or trigger_error(mysql_error());
return mysql_num_rows($results) > 0 ? mysql_fetch_assoc($results) : false;
}
This works great for queries that return 1 row, but how can I get an array returned something like this?
$array[0]['name'] = 'jim'
$array[0]['id'] = 120
$array[1]['name'] = 'judith'
$array[1]['ID'] = 121
Now I know I could use a while loop to insert this data into the array like so, but I was wondering if PHP could do this with an internal function? I havn't been able to find on the docs what I'm after.
The reason I don't want to run the while within the method is because I am going to reiterate back over the array when it's returned, and I'd rather not run through the results twice (for performance reasons).
Is there a way to do this? Do I have a problem with my general query method design?
Thank you muchly!
public function query($queryString)
{
if (!$this->_connected) $this->_connectToDb(); //connect to database
$results = mysql_query($queryString, $this->_dbLink) or trigger_error(mysql_error());
$data = array();
while($row = mysql_fetch_assoc($results))
{
$data[] = $row;
}
return $data;
}
this will always return an array.
EDIT:
I didn't read the question well.
If you realy don't want to use the loop then I would do this:
public function query($queryString)
{
if (!$this->_connected) $this->_connectToDb(); //connect to database
return mysql_query($queryString, $this->_dbLink) or trigger_error(mysql_error());
}
then loop over it, however I would just use the loop.
You might also want to look at the PDO extension. You can load the entire result set into an array or you can loop using foreach.
<?php
$db = new PDO($connection_string, $username, $password);
$result = $db->query($queryString);
foreach($result as $row) {
// do something
}
// or
$result = $db->query($queryString);
$result_array = $result->fetchAll(PDO::FETCH_ASSOC);
?>
Most people use a while() loop in the query to do exactly what you want and then loop over the array to process it.
However, you're right: it wastes memory, which could be a problem with a large dataset. An alternative is for your query method to return the resultset resource. Then your while loop can use that to fetch each row as it requires it.
To abstract that away, I would suggest another class to do that for you. Then your query call would return a new instance of that class which has the MySQL resultset resource as an instance variable and packages up the mysql_fetch_assoc() call.
Look at PEAR::MDB2 (Quickstart Cheatsheet). It provides lots of different functions for doing something like this. It also does not tie you down into using MySQL specific functions because it is a database abstraction layer.
$result = $db->queryRow($query, MDB2_FETCHMODE_ASSOC);
There are other abstraction layers such as ADO as well.
thanks for the ideas. I have a function that returns an associative array from the sql (used in Moodle).
$results = get_records_sql($sql);
//to create a numerically indexed array:
$data = array();
foreach ($results as $row)
{
$data[] = $row;
}
return $data;
}

Categories