How to pass SQL string via function parameter [duplicate] - php

This question already has an answer here:
A helper function for mysqli that dynamically binds params in prepared statement?
(1 answer)
Closed 2 years ago.
I want to create function that take SQL string as parameter and return me an array
I write this function:
function getgquery($I_sql){
$mysqli = new mysqli("localhost","root","","ACLUB");
$sql = $I_sql;
$result = $mysqli->query($sql);
$Data = array();
if(mysqli_num_rows($result)>0){
while($row = mysqli_fetch_assoc($result)){
$Data [] = $row;
}
}
return $Data;
}
And then call the function:
print_r(getgquery('SELECT * FROM `poeple`'));
But I get this error:
Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result,
bool given in N:\xampp\htdocs\test\functions.php on line 9

This is a good idea!
You are getting the error because you haven't enabled error reporting and you do not see the error you are getting for the typo you made in SQL.
The correct function should look something like this:
// Enable mysqli error reporting and open connection
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'username', 'password', 'db_test');
$mysqli->set_charset('utf8mb4'); // always set the charset
function getgquery(mysqli $mysqli, string $I_sql, array $params = []): ?array {
$stmt = $mysqli->prepare($I_sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_BOTH);
}
}
// with the typo fixed:
print_r(getgquery($mysqli, 'SELECT * FROM `people`'));
You need to connect once outside of your function and pass the connection as a parameter.
You need to use prepared statements!
Get rid of this useless loop and num_rows
If you think that passing the connection to this function every time is too much you can create a subclass of mysqli, for example something like this:
class DBClass extends mysqli {
public function __construct(
$host = null,
$username = null,
$passwd = null,
$dbname = null,
$port = null,
$socket = null
) {
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
parent::__construct($host, $username, $passwd, $dbname, $port, $socket);
$this->set_charset('utf8mb4');
}
public function safeQuery(string $sql, array $params = []): ?array {
$stmt = $this->prepare($sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_BOTH);
}
return null;
}
}
and then use it like this:
$mysqli = new DBClass('localhost', 'username', 'password', 'db_test');
$result = $mysqli->safeQuery('SELECT * FROM people WHERE id=?', [$myId]);

Related

Function fetch() when I want to check [duplicate]

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 2 years ago.
I receive this error:
Fatal error: Call to a member function fetch() on boolean in
C:\xampp\htdocs\repo\generator\model\database.php on line 34
When I run this code:
class database
{
private $user = 'root';
private $pass = '';
public $pdo;
public function connect() {
try {
$this->pdo = new PDO('mysql:host=localhost; dbname=generatordatabase', $this->user, $this->pass);
echo 'Połączenie nawiązane!';
}
catch(PDOException $e) {
echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
}
}
public function createTable() {
$q = $this->pdo -> query('SELECT * FROM article');
while($row = $q->fetch()) {
echo $row['id'].' ';
}
$q->closeCursor();
}
}
?>
As per the PHP manual for PDO::query
PDO::query() returns a PDOStatement object, or FALSE on failure.
It looks like your query is failing (on line 33) and thus returning a BOOLEAN (false), likely because at that point in execution, PDO has not connected to a database that contains a table called article. In the connect() method I see that it tries to connect to a db called 'generatordatabase'; ensure this connection is being made prior to calling createTable(), otherwise ensure that it contains a table called 'article'.
I would recommend adding some more code examples, for instance the code that calls this class/method before the error is triggered.
Some error handling will help you avoid issues like this:
$q = $this->pdo->query('SELECT * FROM article');
//error case
if(!$q)
{
die("Execute query error, because: ". print_r($this->pdo->errorInfo(),true) );
}
//success case
else{
//continue flow
}
I'm not sure wheatear this is exactly the error I struggled with, but my error was due to my $con variable, I used a single $con for 2 SQL statements, for example:
$con = new mysqli($host,$username,$password,$database);
$sql = "SELECT name FROM users WHERE email = '$email'";
$stm = $con->prepare($sql);
$stm->execute();
and
$sql1 = "INSERT INTO posts
VALUES('$email','$body')";
$stm1 = $con->prepare($sql1);
if ($stm1->execute()) {
I should have done:
$con = new mysqli($host,$username,$password,$database);
$sql = "SELECT name FROM users WHERE email = '$email'";
$stm = $con->prepare($sql);
$stm->execute();
and
$con1 = new mysqli($host,$username,$password,$database);
$sql1 = "INSERT INTO posts
VALUES('$email','$body')";
$stm1 = $con1->prepare($sql1);
$stm1->execute()

Cannot execute prepared statement "Fatal error: Call to a member function prepare() on null" error

So I have this code
$lang=new language();
$default_language=$lang->getLanguage(0);
$currencies = new currency();
$currencies = $currencies->getCurrencies();
getCurrencies() and getLanguage() are in another file with classes.
public function getCurrencies() {
$curr=new record();
return $curr -> getRecords('currencyTable','currency_order',array("currency_id","currency_name"));
}
public function getLanguage($record) {
$lang=new record();
return $lang->getRecord('languageTable',$record,'lang_order','*');
}
And getRecords and getRecord are public functions it the record class
I keep on getting the error
Fatal error: Call to a member function prepare() on null
Referring to the query of the getRecords functions.
I dont know how to fix this. Does this has to do with the connection to the database?
Also, the weird part is that if I remove the
$lang=new language();
$default_language=$lang->getLanguage(0);
part, this error goes away. Any help? Is the error in the $default_language=$lang->getLanguage(0); line and this is why it is messing up the database connection, resulting to this error?
Thanks
EDIT
Here are the getRecord and getRecords
public function getRecords($table,$sorder,$field_names) {
$conn = db::open();
//- build string of field names
if($field_names!='*'){
$field_string="";
foreach ($field_names as $value) {
$field_string.=",".$value;
}
$field_string = substr($field_string,1);
}else{
$field_string='*';
}
//end up with field1, field2... or *
//soreder is a field, contains int like 1 2 3
//- run statement
$stmt = $conn->prepare("SELECT ".$field_string." FROM ".$table." ORDER BY ".$sorder." ASC");
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results;
}
and
public function getRecord($table,$record,$sorder,$field_names) {
$conn = db::open();
if($field_names!='*'){
$field_string="";
foreach ($field_names as $value) {
$field_string.=",".$value;
}
$field_string = substr($field_string,1);
}else{
$field_string='*';
}
//same things for $field_string and $sorder
$stmt = $conn->prepare("SELECT ".$field_string." FROM ".$table." ORDER BY ".$sorder." LIMIT ? OFFSET ?");
$stmt->bindValue(1, 1 , PDO::PARAM_INT);
$stmt->bindValue(2, $record, PDO::PARAM_INT);
$stmt->execute();
$results = $stmt->fetch(PDO::FETCH_ASSOC);
return $results;
}
I fixed an error. In getRecord I had LIMIT 1 and I fixed it as above. I still get the same error about the getRecords line : $stmt = $conn->prepare("SELECT ".$field_string." FROM ".$table." ORDER BY ".$sorder." ASC");
Any thoughts?
Thanks
Your database connection failed. The error is not in your posted code. The error in your code is when the statement is being prepared.
Ex: $statement = $dbh->prepare("SELECT * FROM some_table"). I would recommend throwing an exception to see what's going wrong with your connection. You can do this by adding the options to your pdo initialization. array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
try{
$dbh = new PDO('mysql:host='.MYSQL_HOST.';dbname='.MYSQL_DB,
MYSQL_USERNAME,
MYSQL_PASSWORD,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
}catch(Exception $e){
echo $e->getMessage();
}
Hope this helps

Call to a member function fetch() on boolean [duplicate]

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 2 years ago.
I receive this error:
Fatal error: Call to a member function fetch() on boolean in
C:\xampp\htdocs\repo\generator\model\database.php on line 34
When I run this code:
class database
{
private $user = 'root';
private $pass = '';
public $pdo;
public function connect() {
try {
$this->pdo = new PDO('mysql:host=localhost; dbname=generatordatabase', $this->user, $this->pass);
echo 'Połączenie nawiązane!';
}
catch(PDOException $e) {
echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
}
}
public function createTable() {
$q = $this->pdo -> query('SELECT * FROM article');
while($row = $q->fetch()) {
echo $row['id'].' ';
}
$q->closeCursor();
}
}
?>
As per the PHP manual for PDO::query
PDO::query() returns a PDOStatement object, or FALSE on failure.
It looks like your query is failing (on line 33) and thus returning a BOOLEAN (false), likely because at that point in execution, PDO has not connected to a database that contains a table called article. In the connect() method I see that it tries to connect to a db called 'generatordatabase'; ensure this connection is being made prior to calling createTable(), otherwise ensure that it contains a table called 'article'.
I would recommend adding some more code examples, for instance the code that calls this class/method before the error is triggered.
Some error handling will help you avoid issues like this:
$q = $this->pdo->query('SELECT * FROM article');
//error case
if(!$q)
{
die("Execute query error, because: ". print_r($this->pdo->errorInfo(),true) );
}
//success case
else{
//continue flow
}
I'm not sure wheatear this is exactly the error I struggled with, but my error was due to my $con variable, I used a single $con for 2 SQL statements, for example:
$con = new mysqli($host,$username,$password,$database);
$sql = "SELECT name FROM users WHERE email = '$email'";
$stm = $con->prepare($sql);
$stm->execute();
and
$sql1 = "INSERT INTO posts
VALUES('$email','$body')";
$stm1 = $con->prepare($sql1);
if ($stm1->execute()) {
I should have done:
$con = new mysqli($host,$username,$password,$database);
$sql = "SELECT name FROM users WHERE email = '$email'";
$stm = $con->prepare($sql);
$stm->execute();
and
$con1 = new mysqli($host,$username,$password,$database);
$sql1 = "INSERT INTO posts
VALUES('$email','$body')";
$stm1 = $con1->prepare($sql1);
$stm1->execute()

PHP database connection class bind_param

I would like to write a database connection class and I dont understand how I have to write the select method with bind_param-s. Here is the full code. And here the part of the code where I need the help:
public function select($sql){
$db = $this->connect(); //This methos connect to the DB
$stmt = $db->prepare($sql);
if($stmt === false){ //If the prepare faild
trigger_error("Wrong SQL", E_USER_ERROR);
}
$error = $stmt->bind_param("i", $id);
if($error){
return "Error: ".$stmt->error, $stmt->errno;
}
$err = $stmt->execute();
if($error){
return "Error: ".$stmt->error, $stmt->errno;
}
$result = $stmt->bind_result($id);
$stmt->close();
$dbConnection->closeConnection($db);
return $result;
}
I need to got it parameters or how can I slove it?
You need to pass your values into this function too. And eventually bind them into prepared statement.
Optionally you can pass string with types, but by default all "s" will do.
Also remember that you should connect only ONCE per script execution. and then use one single connection all the way throughout your code.
And get rid of all these error checks. Set mysqli in exception mode instead.
public function q($sql, $values = array(), $types = NULL)
{
$stm = $this->mysql->prepare($sql);
if (!$types)
{
$types = str_repeat("s", count($values));
}
if (strnatcmp(phpversion(),'5.3') >= 0)
{
$bind = array();
foreach($values as $key => $val)
{
$bind[$key] = &$values[$key];
}
} else {
$bind = $values;
}
array_unshift($bind, $types);
call_user_func_array(array($stm, 'bind_param'), $bind);
$stm->execute();
return $stm->get_result();
}
so it can be used like this
$res = $db->q("SELECT name FROM users WHERE id=?", [$id]);
or
$res = $db->q("SELECT name FROM users WHERE id=?", [$id], "i");
your other functions have to be changed as well.
class DB{
public $con;
function __construct()
{
$this->con = new mysqli("localhost", "root", "", "proba_fferenc");
}
public function select(...)
{
// as shown above
}
}

PDO - Iteratively Binding Variables

I am trying to create a function to iteratively bind variables. This is what I have so far:
function prepareQuery($db, $query, $args) {
// Returns a prepared statement
$stmt = $db->prepare($query);
foreach ($args as $arg => $value) {
$stmt->bindParam($arg, $value);
}
return $stmt;
}
This is how I'm using it:
$stmt = prepareQuery($db, "SELECT * FROM `Licenses` WHERE `verCode`=:verCode", Array(":verCode" => $verCode));
$verCode = "some_string";
$stmt->execute();
while ($info = $stmt->fetch()) {
print_r($info);
}
Though it doesn't print anything. I know the database entry exists, and the same query works from PHPMyAdmin. So, I think it's just a problem in how my function tries to create the bindings. How can I fix this? Thanks!
Do not create a function to iteratively bind variables. PDO can do it already
function prepareQuery($db, $query, $args) {
$stmt = $db->prepare($query);
$stmt->execute($args);
return $stmt;
}
If it doesn't print anything, then it didn't find anything. As simple as that.
You don't even need this prepare query function actually. Just amend PDO very little like this
class myPDOStatement extends PDOStatement
{
function execute($data = array())
{
parent::execute($data);
return $this;
}
}
$user = 'root';
$pass = '';
$dsn = 'mysql:charset=utf8;dbname=test;host=localhost';
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => TRUE,
PDO::ATTR_STATEMENT_CLASS => array('myPDOStatement'),
);
$pdo = new PDO($dsn, $user, $pass, $opt);
and you'll be able to write such a neat chain:
$sql = "SELECT * FROM `Licenses` WHERE `verCode`=:verCode";
$code = "some_string";
$data = $pdo->prepare($sql)->execute([$code])->fetchAll();
foreach ($data as $info) {
print_r($info);
}

Categories