Undefined variable niggles - php

Below is my class. Fig A
<?php
class qcon{
public static $conn;
function dbcon()
{
if (!$conn)
{
$host = 'x';
$username = 'x';
$password = 'x';
$dbname = 'x';
$conn = mysqli_connect($host , $username , $password ,$dbname);
}
return $conn;
}
}
?>
Which is called here. Fig B
require_once(class file above);
function openSesame()
{
$boogey = new qcon();
$conn = $boogey->dbcon();
if (!$conn)
{
$this->error_msg = "connection error could not connect to the database:! ";
return false;
}
$this->conn = $conn;
return true;
}
Is causing
Notice: Undefined variable: conn in C:\...\xxxx\figAclass.php on line 10
I know I can simply turn errors off, but this seems unwise. I took a look at a generic SO question about the undefined variable notice. Obviously the advice was general - use isset. Had a go at isset and this does not seem correct for what I am trying to do.
Based on the code in figure A and B, is there anything obvious causing the notice to be flagged up. Could you demonstrate a fix that is in line with the existing code shown.

Don't use if (!$conn), which will check to see if the variable is true/false or contains a value, not if it's defined. Use this instead:
if(empty($conn))
This checks to see if the variable is defined, and if it is NULL/empty.
You also want to use $this->conn inside of your class instead, since you're defining it as a variable of the class.

Like I said in my comment above, since you have a static $conn, you need to refer to it like:
public function dbconn()
{
if (!self::$conn) {
// blah
}
return self::$conn;
}
Your error is happening because you're attempting to reference a variable named $conn, but due to scope, no such thing exists.

when you access it, you should use $this->conn, in example:
if(!$this->conn){...}
edited read the question too fast, sorry

You can't use if (!$conn)for this because that will only return 'true' or 'false'.
Use:
if empty($conn) instead.

Related

Classes and methods with PDO, and retrieving the data

I'm new to OOP programming, and I'm really lost with this what the title says. When I try to put the query in a class and in another file, I get errors in a file called Main.php and don't even know what to do to fix them:
Notice: Undefined variable: sth in Select.php on line 10
Fatal error: Cannot access empty property in Select.php on line 10
If I put the select in Connection.php, it returns the rows just fine, but with classes, I get those.
Here's my code:
Connection.php:
<?php
$hostname = 'localhost';
$username = 'user';
$password = 'pass';
function connectDB ($hostname, $username, $password){
$dbh = new PDO("mysql:host=$hostname;dbname=database", $username, $password);
return $dbh;
}
$dbh = connectDB ($hostname, $username, $password);
echo 'Connected to database <br/>';
Select.php:
<?php require_once 'Connection.php';
class Select {
public function select() {
$sql= "select * from table limit 10; <br/>";
echo $sql;
$select = $dbh->query($sql)->fetchall(PDO::FETCH_ASSOC);
foreach($this->$sth as $row){
echo $row['column']."<br/>";
}
}
}
The question is, how can I print the result from the query (for example from main.php, which has an autoloader), and why do I get those errors, when on a single file, they work just fine?
Edit:
<?php
$test = new Select($dbh);
echo $test->select();
?>
Besides the fixes in the replies, I included Connection.php into the main.php, changed the echo in Select.php to return and it works perfectly now. Adding this in case someone ever gets as lost as me.
You do not want to iterate over the query, but the result of that query. So this probably is what you are looking for:
<?php
class Select {
public function select() {
$sql= 'select * from table limit 10';
$select = $dbh->query($sql)->fetchall(PDO::FETCH_ASSOC);
foreach($select as $row){
echo $row['column']."<br/>";
}
}
}
And you also need to take care that the $dbh object is actually present inside that method. Either inject it into the object or specify it as method argument. So your full class will probably look something like that:
<?php
class Select {
private $dbh;
public function __construct($dbh) {
$this->dbh = $dbh;
}
public function select() {
$sql= 'select * from table limit 10';
$select = $this->dbh->query($sql)->fetchall(PDO::FETCH_ASSOC);
foreach($select as $row){
echo $row['column']."<br/>";
}
}
}
And you instantiate the object like that:
$selectObj = new Select($dbh);
Some general warning, though: Using PDO's fetchall() method is convenient, but carries a huge risk: it means that the full result set has to be copied into an array inside the php script. For bigger results that may lead to issues with memory usage (scripts getting terminated for security reasons). Often it is the better approach to use a while loop over a single row fetched from the result set in each iteration.

Is this right way to use php oop and mysqli?

I am not very experienced in php oop. Moreover, when mysqli comes with php oop, it make me more confused about using it in best efficient way. Anyway, first look at my connection class:
<?php
//connectionclass.php
class connection{
public $conn;
public $warn;
public $err;
function __construct(){
$this->connect();
}
private function connect(){
$this->conn = # new mysqli('localhost', 'sever_user', 'user_password');
if ($this->conn->connect_error) {
$this->conn = FALSE;
$this->warn = '<br />Failed to connect database! Please try again later';
}
}
public function get_data($qry){
$result = $this->conn->query($qry);
if($result->num_rows>=1){
return $result;
}else{
$this->err = $this->conn->error;
return FALSE;
}
$result->free();
}
public function post_data($qry){
$this->conn->query($qry);
if($this->conn->affected_rows>=1){
return TRUE;
}else{
$this->err = $this->conn->error;
return FALSE;
}
}
}
?>
Now please structure of a php page which uses mysql database to store and get data:
<?php
//login.php
include('/include/connectionclass.php');
$db = new connection();
$query = "SELECT * FROM USERS WHERE user_country='India'";
$data = $db->get_data($query);
if($data){
while($row=$data->fetch_assoc()){
echo 'User Name: ':.$row["user_name"].' Age: '.$row["age"];
}
}
?>
So my login.php uses connection class to get data about users. All the things are running well. But one things made me confused. In connectionclass.php $this->conn is itself an object as it calls new mysqli. So this is an object inside another object $db. Moreover, When I am using $data = $db->get_data($query);, a result set is created inside object $db by method get_data, then this result set is copied into a variable $data inside login.php page.
So according to me, actually two result sets/data sets are creating here, one inside db object and one inside login page. Is it right way to use mysqli and php to get dataset from mysql database? Will it use more memory and server resources when the dataset is larger (when have to get large amount of data for many users)?
If it is not right way, please explain your points and please give me code which can be used efficiently for php oop and mysqli.

DB connections. SQL retrieve error

I define all my connections on an external file called db_config.php
This enables my class files to use db_config.php file for connections.
However, I am wondering if someone could shed some light on the following error.
SQL Retrieve Error: No database selected
This is referring to this line of code on db_config.php.
return array("host"=>"x", "username"=>"x", "password"=>"x", "dbname"=>"x" );
This is the function that makes the call
function openDB() {
$config = include_once("assets/configs/db_config.php");
$conn = mysqli_connect(
$config["host"] , $config["username"],
$config["password"], $config["dbname"]);
$this->conn = $conn;
return true;
}
What am I missing?
First of all make sure the variables in the config file are correct. If they are correct the try changing the include_once to include.
if that is not working, then change the code to :
function openDB() {
$config = array("host"=>"x", "username"=>"x", "password"=>"x", "dbname"=>"x" );
$conn = mysqli_connect(
$config["host"] , $config["username"],
$config["password"], $config["dbname"]);
$this->conn = $conn;
return true;
}
See if this works my way. If it does then your won't need the db.php file.
Please dump the $config variable and check what is going wrong ,
<?php
var_dump($config);
?>
So you can find $config is returning an array or not !

PDOException not triggering / possible scope related?

In anticipation of mysql_query being deprecated PHP 5.5.0, I have been working on a class to handle all my DB queries :
class DataBaseClass {
//.....some other function and variables declared here....
function GetConnection() {
try {
$this->conn = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS);
$this->conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch(PDOException $e) {
echo $e->getMessage();
}
return $this->conn;
}
function Query($str_sql, $arr_parameters = array()) {
try {
$this->str_mysql_error = $this->int_num_rows = $this->int_num_affected_rows = $this->int_mysql_insert_id = '';
if (count($arr_parameters) > 0) {
$obj_result = $this->conn->prepare($str_sql);
$obj_result->execute($arr_parameters);
} else {
$obj_result = $this->conn->query($str_sql);
}
}
catch(PDOException $e) {
$this->str_mysql_error = $e->getMessage() . $str_sql;
}
}
}
Then I have another class to create new user:
class AddNewUser {
//.....some other function and variables declared here....
function InsertUser() {
$str_sql = "INSERT INTO (uname, name, email, pass, user_regdate, theme) VALUES )";
$_SESSION['db_connection']->Query($str_sql, '');
}
}
Now on my main user creation page I have :
$_SESSION['db_connection'] = new DataBaseClass;
//Reason I used $_SESSION to store my DB object, is so that it can be accessible everywhere.
//Did not want to use "global" everywhere. Not sure if this is he best way???
$cls_new_user = new AddNewUser ();
$cls_new_user->InsertUser(); //Does not raise PDOExecption although SQL cleary wrong inside this method
if ( $_SESSION['db_connection']->str_mysql_error) {
//show error in error div
}
$str_sql = "SELECT some wrong SQL statment";
$_SESSION['db_connection']->Query($str_sql); // This does raise PDOExecption
if ( $_SESSION['db_connection']->str_mysql_error) {
//show error in error div
}
I'm not sure why the DB class function "Query" would not raise an exception on clearly wrong SQL when called from another class. But same function called from main page code (not inside function / class) raises and exception error.
Also, the "InsertUser" function does not execute / insert anything into DB even if SQL correct.
Could it be scope related, or the fact that I'm trying to enforce global scope of my DB object by putting it in $_SESSION ??
Am I going about this the wrong way? Reason for going class route to encapsulate all my DB calls was to avoid any deprecation issues in future - only having to update class.
Make your function this way.
function Query($str_sql, $arr_parameters = array()) {
$stmt = $this->conn->prepare($str_sql);
$stmt->execute($arr_parameters);
}
I am pretty sure that exception would be thrown
The only issue can be with catching exceptions, not throwing. And it could be caused by Namespace, not scope. To be certain, you can always prepend all PDO calls with a slash:
\PDO::FETCH_ASSOC
\PDOException
etc.

PHP prepared statement: Why is this throwing a fatal error?

Have no idea whats going wrong here. Keeps throwing...
Fatal error: Call to a member function prepare() on a non-object
...every time it gets to the $select = $dbcon->prepare('SELECT * FROM tester1');part. Can somebody shed some light as to what I'm doing wrong?
function selectall() //returns array $client[][]. first brace indicates the row. second indicates the field
{
global $dbcon;
$select = $dbcon->prepare('SELECT * FROM tester1');
if ($select->execute(array()))
{
$query = $select->fetchall();
$i = 0;
foreach ($query as $row)
{
$client[$i][0] = $row['id'];
$client[$i][1] = $row['name'];
$client[$i][2] = $row['age'];
$i++;
}
}
return $client;
}
$client = selectall();
echo $client[0][0];
The obvious answer is that $dbcon hasn't been initialized at all or is initialized after this function is called.
What code is initializing $dbcon? Where and when is it run? You also realize that you will need to initialize it on every invocation of a script that accesses the database? The last is just to make sure that you understand what the global scope in PHP is. It means scoped to that single request. The term global is a little misleading.
make sure you define $dbcon properly. If you are using mysqli, see how the connection is setup in the doc. you can also pass the connection object to the function
function selectall($dbcon){
....
}

Categories