Since moving to PHP 8 the code below now gives me the error 'Fatal error: Uncaught Error: Non-static method mysqli_result::fetch_array() cannot be called statically...'
if (!isset($isone)) {
$seestuno=isset($_POST['seestuno']);
}
if (isset($seestuno)) {
include ('/home/username/private/dblon.php'); //database connection ($dbcnx below)
$sql="SELECT stuno,fname,lname FROM Studetails WHERE stuno=$seestuno";
$result=#mysqli_query($dbcnx, $sql);
$row=#mysqli_result::fetch_array($result); //I changed from mysql_fetch_array. I believe this is more correct?
The bottom line gives the error. I thought this was basic stuff (since I did it) so can anyone help me out? Many thanks.
mysqli_result::fetch_array ( int $mode = MYSQLI_BOTH ) is the method signature for the method "fetch_array" of the mysqli_result class. Therefore, you'd have to call it as an object method:
$row = $result->fetch_array();
Or, of course, you use the equivalent to mysql_fetch_array instead:
$row = mysqli_fetch_array($result);
There are examples at the bottom of the official docs for that. The rest of your code uses mysqli's procedural interface, so I'd stick to the later case unless all mysqli calls are converted to object oriented style.
:: is a scope resolution operator and is used to access static and constant members of a class.
fetch_array() is not a static method. You can't access it statically. It is an instance method that can be called on every object.
To call a method on an object you have to use object operator ->.
When you fix your code, it should look something like this:
if (!isset($isone)) {
$seestuno = isset($_POST['seestuno']);
}
if (isset($seestuno)) {
include '/home/username/private/dblon.php'; //database connection ($dbcnx below)
$stmt = $dbcnx->prepare("SELECT stuno,fname,lname FROM Studetails WHERE stuno=?");
$stmt->bind_param('s', $seestuno);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_array($result);
}
Related
I have cerb2 https://github.com/wgm/cerb2, it is an old ticketing system, it might looks weird but I have a a lot of knowledgeable information burried that I want to exploit.
It is basically a PHP5/Mysql software with the mysql_connect() constructor
The main issues are queries that stay null at all times. The code base lays on Class definition and pseudo-variable $this to call a query method from another Class.
function CER_HASH_QUEUES(&$parent)
{
global $session;
global $queue_access; e();
$this->db = (new cer_Database())->getInstance();
$this->_parent = &$parent;
if(empty($queue_access))
$this->queue_access = new CER_QUEUE_ACCESS();
else
$this->queue_access = $queue_access;
$sql = "SELECT q.queue_id, q.queue_name FROM queue q ORDER BY q.queue_name";
$res = $this->_db->query($sql);
That last line ($res =… ) is stopping code execution with:
Fatal error: Call to a member function query() on null in
The Query method called from cer_Database.class looks like this ( https://raw.githubusercontent.com/wgm/cerb2/stable/cerberus-api/database/cer_Database.class.php )
function query($sqlString,$return_assoc=true)
{
$config_db = (new cerConfiguration())->getInstance();
if($return_assoc === true) $this->db->SetFetchMode(ADODB_FETCH_ASSOC);
else $this->db->SetFetchMode(ADODB_FETCH_NUM);
$res = $this->db->Execute($sqlString);
if($cfg->settings["debug_mode"]) {
$time_end = microtime();
$query_time = microtime_diff($time_end,$time_start) * 1000; // convert secs to millisecs
echo "<b>[CERBERUS QUERY]:</b> " . $sqlString . " (Ran: <b>" . sprintf("%0.3f",$query_time) . "ms</b>)<hr>";
}
return $res;
}
That last method depends on a second Class cerConfiguration() which relies on import_config_db() to construct the mysql connector.
I am unable to figure out how to pass successfully my sql request following the design pattern carried by the relevant software here.
The databases and the tables are OK on their sides, and the following php script is returning the sql query OK.
<?php
include('includes/third_party/adodb/adodb.inc.php');
$db = ADONewConnection('mysql');
$db->Connect("localhost", "user", "pass", "databasename");
$rs = $db->Execute('SELECT q.queue_id, q.queue_name FROM queue q ORDER BY q.queue_name');
print "<pre>";
print_r($rs->GetRows());
print "</pre>";
I guess without the object oriented design pattern understanding used by PHP I am going to struggle to resuscitate that old piece of software.
Any help, ideas very welcome.
Yours.
Fatal error: Call to a member function query() on null in
You are likely to find further issues in your investigation, but the problem you're asking for help with is relatively simple.
The database property in the class is defined early on in your code as $this->db, but you are then trying to access it as $this->_db. The underscore makes it a different variable name, and thus it doesn't exist. So it is null, hence why you are getting Call to a member function query() on null.
To fix it, make sure you're using the same name for it throughout the class.
This question already has answers here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(1 answer)
MySQLi prepared statements error reporting [duplicate]
(3 answers)
Closed 4 years ago.
I am looking for a way to build a handler or edit a php object, the following is an example for mysqli
I have a system with many files using the mysqli object in a variable
$my_var=new mysqli($host, $user, $pass, $base);
Files call this to do queries and get the results like this:
$q=$my_var->query("SELECT * FROM table");
$q->fetch_assoc();
if there is an error on the query, $my_var->error will be populated on the first line and will throw an error 500 on the second line.
I am looking for a way to build a handler for $my_var->error and throw the error before any fetch_* method is called, so,
is there any way to build a handler/listener for $my_var->error?
if this is not possible, is there any way to override mysqli fetch_assoc(), fetch_row() and fetch_array() methods to check if $my_var->error is true and show the error before continue?
I know about try{}catch(), throw new Exception and or die() methods, but these mean to edit every fetch_* in the system, I would like to do it editing the connection file only.
Thank you!
---editing---
I think prepared statements are not what I am looking for.
---editing 2---
And no, I am not looking how to get mysqli errors.
Thank you for your help fyrye!
---Answer Final Code---
class mysqli2{
private $c;
function __construct(...$args){ // open connection
$this->c=new mysqli(...$args);
if(!empty($this->c->error)){ // check for errors
echo("<script>console.error(\"MySQL: ".$this->c->error."\");</script>");
}
}
function query($query, $resultmode = MYSQLI_STORE_RESULT){
$r=$this->c->query($query, $resultmode); // make query
if(!empty($this->c->error)){ // check for errors
echo("<script>console.error(\"MySQL: ".$this->c->error."\");</script>");
}
return $r; // returns query results
}
function __call($method, $args){ // calls others mysqli methods
return $this->c->$method(...$args);
}
function __get($name){ // get all the properties
return $this->c->$name;
}
function __set($name, $value){ // set all the properties
if (property_exists($this->c, $name))$this->c->$name = $value;
}
}
To suggest a best practice, when using either PDO or MySQLi extensions, it is suggested to always check the return results from any of the usable methods, before moving on to a method that relies on its result.
As mysqli::query returns false on an error, it should be checked before using fetch_assoc, instead of assuming it is not false. The same applies to using fetch_assoc, as it can return NULL;
if (!$q = $my_var->query($sql)) {
//something went wrong - handle the error here.
}
if ($data = $q->fetch_assoc()) {
echo $data['column'];
}
However as I suggested, you would need to create an abstraction layer.
Since $q would be false on error, the exception from the code in your question would be:
Fatal error: Call to a member function fetch_assoc() on boolean
Meaning you would not be able to override the fetch_* methods, without overriding mysqli::query to always return an object.
Please do not use in production code.
This is only an example of how to override the mysqli::query method with your own. You would also need to override all other mysqli::*** methods, like prepare, commit, etc.
Example https://3v4l.org/PlZEs
class Conn
{
private $conn;
public function __construct(...$args)
{
$this->conn = new mysqli(...$args);
}
public function query($query, $resultmode = \MYSQLI_STORE_RESULT)
{
$d = $this->conn->query($query, $resultmode);
if (!empty($this->conn->error)) {
throw new \RuntimeException($this->conn->error);
}
return $d;
}
}
//Your connection code
$con = 'my_var';
$$con = new Conn('host', 'user', 'pass', 'base');
//example usage of valid query
$q = $my_var->query('Valid Query');
$q->fetch_assoc();
//example use of invalid query throwing an exception before `fetch_assoc`
$q = $my_var->query('This is not valid');
$q->fetch_assoc();
Results
I was successful
-----
Fatal error: Uncaught exception 'RuntimeException' with message 'Expected "Valid Query"' in /in/PlZEs:51
Stack trace:
#0 /in/PlZEs(70): Conn->query('This is not val...')
#1 {main}
thrown in /in/PlZEs on line 51
This approach uses PHP 5.6 argument packing and unpacking, to match the function call arguments, to prevent having to manually define them.
It is possible to expand on this to write a message to log file, send an email, trigger an event, or display a friendly error message instead of throwing an exception. As well as overriding the mysqli_stmt responses with your own Statement object(s).
With PHP I know how to access databases using mysql_query(), PDO->query() and pdo->prepare() followed by PDO->bindParam() and PDO->execute().
However in the past I have come across a method of database access where you have a class object which contains variable names which mirror the fields in a database and you change the field values to interact with the database.
I have only seen this done in C# however. The C# object is known as a POCO object and looks like a class with only variables in it.
Is it possible to do something similar in PHP PDO.
The simplest solution is to use PDO with PDO::FETCH_OBJ or PDO::FETCH_CLASS.
See documentation:
http://www.php.net/manual/en/pdostatement.fetch.php
http://www.php.net/manual/en/pdostatement.setfetchmode.php
Example:
$stmt = $pdo->prepare(...);
$stmt->execute();
while ($obj = $stmt->fetch(PDO::FETCH_OBJ)) {
// $obj is a new object of class stdClass
echo $obj->columnname
}
Example:
$stmt = $pdo->prepare(...);
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_CLASS, 'MyClass');
while ($obj = $stmt->fetch()) {
// $obj is a new object of class MyClass
echo $obj->columnname
}
That's something I was curious. In php mysqli I can do action function over the unknown class name, for example:
$res = $mysqli->query($query);
$res->fetch_array();
That is the name of the fetch_array known, but the res variable. I would like to know how it is implemented. Sorry for the sloppy google translation.
If I understand your question correctly, then the answer is that method mysqli::query returns object that is instance of class mysqli_result. This class has method fetch_array().
Also, you may be interested in function get_class.
Before this line:
$res = $mysqli->query($query);
There was for sure mysqli connection:
$mysqli = new mysqli("localhost", "user", "password", "database");
From this, mysqli is a class which is ready for you that provided by PHP, consider its like this:
class mysqli{
}
The, $res is copy of $mysqli->query($query); which is:
here query is a property of mysqli class (a function), we do this to copy the result of mysqli query which is resource for (success) and false for failure.
You can also combine like this:
$row = $mysqli->query($query)->fetch_array();
print_r($row);
My guess is
class MySQLi{
/* other code */
public function query($query){
// some code
return new MySQLiResult(); // Don't know if that's the real class name
}
}
And the result should look like this
class MySQLiResult{
public function fetch_array(){
return array();
}
}
Note, that I've only written imaginary code. I don't really know, what the class names are.
It's only a rough estimate of how it should look.
I have a really odd error:
[04-Jun-2010 15:55:32] PHP Catchable
fatal error: Object of class Type
could not be converted to string in
/home/prettykl/public_html/2010/includes/functions.php
on line 140
This is the code and line 140 is the $sql line.
if (!empty($type)) {
$sql = "SELECT * FROM `types` WHERE `type` = '$type'";
$dbi = new db();
$result = $dbi->query($sql);
$row = mysql_fetch_row($result);
$dbi->closeLink();
$where_array[] = "`typeID` = '".$row->typeID."'";
$where_array[] = "`typeID2` = '".$row->typeID."'";
}
I have 5 or 6 classes and I've never encountered this problem before.
The function has no reference to the classes, any ideas??
Thanks,
Stefan
$type is an object of the class Type. You probably want to query a property of that object?
The error means that $type is actually an object (of class Type), so either the $type variable doesn't contain what you expect, or you actually want to get a member of the object instead, so $type->getSomeString(), etc.
This error happens when you try to convert an object to string and the object doesn't implement the __toString() method. PHP can't handle that conversion. For instance:
$s = new stdClass();
echo $s;
Catchable fatal error: Object of class stdClass could not be converted to
string in php shell code on line 1
Note that you are outputting $type inside the query, as if it was a string.