I've been using this solution to get a superglobal mysqli connection:
class blst_db {
private static $mysqli;
private function __construct(){} //no instantiation
static function cxn() {
if( !self::$mysqli ) {
self::$mysqli = new mysqli(...);
}
return self::$mysqli;
}
//use
blst_db::cxn()->prepare(....
I found it here and it was working fine but when I try to get two connections at the same time I get an error. For example, I've a class that runs a query like this one:
$query_points = blst_db::cnx()->prepare('SELECT point_id FROM points WHERE id=?');
$query_points->bind_param('i', $this->id);
$query_points->bind_result($point_id);
$query_points->execute();
while ($query_points->fetch()) {
$point = new blst_point ($point_id);
$points[] = $point; }
I'm creating various objects inside the while statement and that objects constructor runs another query each time (another $query=blst_db::cnx->prepare(...)) and that's the one that is not working and I can't find the problem. If I change the code and create an array inside the while statement and then, after closing that query, I create all the objects inside a foreach I get no problem but I don't like that solution.
Thank you!
I found the problem. I have to store the results from the first query so I can run the rest inside it. I just added:
$query_points->store_result();
after the execute() call and then I made a free_result() before closing the $query_points and it's working perfectly.
I've found the solution here.
Related
This question already has an answer here:
How to use PDO connection in other classes?
(1 answer)
Closed 2 years ago.
I have 2 class in my CMS and there are crud functions in "User Class". How can I use database class in another class. I know they both work. But I was previously transferring with the "extends" method. But every time I created an object, the database connection was duplicated. So "extends" was fault for me. I don't want to fault again.
So which is best solution? Do any of these solutions duplicate the database connection?
databaseclass.php:
class database
{
public $connect;
function __construct() {
$this->connect();
}
public function connect() {
$this->connect = new PDO('mysql:host=' . SERVER . ';dbname=' . DB_NAME . ';charset=utf8', DB_USER, DB_PASS);
}
}
userclass.php:
class user
{
function getUser() {
# select an user codes
}
}
Solution - Injection database class
class user
{
function getUser($database) {
$mysql_command = $database->connection->prepare('SELECT * FROM users WHERE id = 1');
$mysql_command->execute();
return $mysql_command->fetch(PDO::FETCH_ASSOC);
}
}
Solution - Global database class (I want that but everybody suggest first solution) (I want because this solution does not require me to inject each time I create a user object) userclass.php:
class user
{
function getUser() {
global $database;
$mysql_command = $database->connection->prepare('SELECT * FROM users WHERE id = 1');
$mysql_command->execute();
return $mysql_command->fetch(PDO::FETCH_ASSOC);
}
}
I added a third option here and gave some personal opinion about the others:
Solution a) Pass as parameter to your methods
This way you always need to pass it inside your functions which makes the API of your class less clean. Imagine we want to get a user by id. This could look like: getUserById($database, 123). This will require everywhere to know how to fetch the databse. I would try to avoid this.
Solution b) Use it as global
I would try avoid global wherever I can. My first argument would be that it makes your class less testable and can change the behaviour dependent on the context. Here is a nice post about it with more examples: https://stackoverflow.com/a/5166527/12880865
Solution c) Use dependency injection with the __constructor.
I would add another way of solving it by using dependency injection at constructor level already. This way you can use getUsers() or getUserById($id) without passing the database all the time. This way your class defines it's own dependencies very clearly for the user of this class.
this solution does not require me to inject each time I create a user object
To avoid this you could use container which could resolves your class dependencies automatically when you try to retrieve them.
Example with your code:
class user
{
protected $database;
public function __construct(database $database) {
$this->database = $database;
}
function all() {
# select an user codes
$this->database->query('....');
}
function getById($id) {
# select an user codes
$this->database->query('....', ['id' => $id]);
}
}
which you can then inject like this:
$database = new Database();
// Here you'll pass your database connection into the repository
$users = new UserRepository($database);
$users->all(); // returns an array of all users
$users->getById(123); // returns a specific user by id
// Here you'll pass the same database connection into another repository
$posts = new PostRepository($database);
$posts->all(); // returns an array of all posts
$posts->getById(123); // returns a specific post by id
I'm new to PHP and just started to learn it. There is this problem that I'm working on it for quite a time now but nothing seems to work.
well, the problem is that I have a piece of code for a web page and I need it to be executed only once. By that I mean the code must be executed when the very first client views the webpage and stop working for the second and other clients who view the page.
I have tried "include" and "required once" but these execute code once per run. I have also tried using session but it this case also the code executes once for each client.
And Also, yes I know I can use a flag and check database to make this work, but I wanna know that PHP has it handled or not
So I'm kinda stuck here.
We know that PHP is the server side language; therefore does it have any feature which executes a code once and stores the results in its global space?
Here is my code, I read data from excel and then I create my array of items.
// foreach row
// I read $col1 ..$col6 from excel for each row
new itemdata($col1,$col2,$col3,$col4,$col5,$col6);
class itemdata
{
public $item;
public $cat;
public $unit;
public $prec;
public $alarmType;
public $order;
static $items=array();
function __construct($item,$cat,$unit,$prec,$alarm,$order)
{
$this->item = $item ;
$this->cat = $cat;
$this->unit = $unit;
$this->prec = $prec ;
$this->alarmType = $alarm;
$this->order = $order;
array_push(self::$items,$this);
}
// And some methods for searching declared array 'items'
I need to execute this code once at all .
I appreciate your help.
I am working small php project and i am using singleton database class from this repo
The problem is i can't get query result as array value.Here is my code
Core.php
class Core extends Database
{
public static function run($sql)
{
return parent::getInstance()->getConnection()->query($sql);
}
public function getUniversities()
{
$sql = 'SELECT * FROM `adm_universities`';
return Core::run($sql);
}
}
//get the data from db
$result=Core::getUniversities();
print_r($result);
But the PDOStatement Object returns only the queryString not the result array.
what's wrong with this code?
You can either use foreach loop over PDOStatement or get a conventional array from it using fetchAll() method.
foreach ($result as $row) ...
// or
$data = $result->fetchAll();
print_r($data);
Note that this singleton class makes very little sense as it doesn't support prepared statements.
Also, there should be no getUniversities() in the Core class. That's bizarre thing for the OOP.
You have not used fetch or fetchall or find it seems.
Check the pdo manual properly.
You have to execute the query and then you have to use result functions to get the result array
I've made this class to handle all of my sql-queries. But I'm unsure of how to use it properly.
The class looks something like this (this is a VERY simple version of it):
class sql {
private $conn;
private $data;
function __construct() {
//makes connection to DB and sets $conn and $data
}
public function select($variables, $table, $criterias) {
//returns an array with all the info from DB
}
function __destruct() {
//closes the sql-connection
}
}
The question now is: Is this going to overload the DB, if I use it multiple times on every page-load? (refered to as Example #1)
$dbInfo = (new sql)->select($var,$tab,$cri);
$moreInfo = (new sql)->select($var2,$tab2,$cri2);
$evenMoreInfo = (new sql)->select($var3,$tab3,$cri3);
Would it be beneficial to make my sql class's methods static?
Or should I not create a new instance of a sql object every time I want to make a query (like the example below - refered to as Example #2)?
$sql = new sql();
$dbInfo = $sql->select($var,$tab,$cri);
$moreInfo = $sql->select($var2,$tab2,$cri2);
$evenMoreInfo = $sql->select($var3,$tab3,$cri3);
How and when is Example #1 the better choice over Example #2, and vice versa?
If I assume that Example #1 is going to take the most resources from the DB, when would you pick Example #1 over Example #2?
Your example 2 is more common to see, however the SQL object is usually a static/singleton. So it connects to the database once per server request.
Your base SQL object should handle connecting to a database and then handle basic input/output, such as executing a string of SQL and returning the results.
You can then add new objects on top of that for each object/table than then interfaces with this SQL singleton. These classes will handle constructing their custom SQL based on their table, joins, field names/types, etc.
E.g:
A very basic 'table' object looks like this
class SomeTableObject
{
m_TableName = 'SomeTable'; // Table to get Data from
function GetSelectSQL()
{
return "SELECT * FROM ".$this->m_TableName;
}
function Select($where)
{
$sql = $this->GetSelectSQL().$where;
return SqlSingleton::Execute($sql);
}
function GetByID($id)
{
$where = " WHERE FieldNameForID=$id";
return $this->Select($where);
}
}
These objects work better if they extend a base class that has those basic GetSelectSQL, TableName, Select, etc functions. The GetByIDs (and other gets, updates, inserts) will vary from table to table.
I've got a PHP database class which connects to MySQL and wraps up all the PDO code and I use it to query the database. Basically in the page controller I make a new object:
$db = new Database($dbConfig);
Then I can get data from the database like so using a prepared query:
$params = array('username' => $username);
$result = $db->preparedSelect('select password, salt from users where username = :username', $params);
Which copies the PDO statement results into a new assoc array and returns just the database results back to the calling page. I iterate through them with a simple foreach like so:
foreach ($result as $key => $val)
{
$password = $val['password'];
$salt = $val['salt'];
}
Ok so lets say I want another class to use my $db object so it can access the database in some of the methods. At the moment the other class looks like this:
class General
{
// Database object
private $db;
public function __construct($db)
{
$this->db = $db;
}
}
That works well but I'm just wondering if the constructor should look like this:
public function __construct(&$db)
{
$this->db = $db;
}
That should mean I'm passing it in via reference and not copying the object into the other class. I don't want a copy of the $db object inside the class, I want it to use the existing database object so I don't have multiple copies of it floating around using up memory.
Is there any difference in PHP5 between passing it in as $db or &$db? From doing some reading, PHP5 by default passes objects by reference, and other people saying it now does it the Java way and some say using the & makes a hard link whatever that is. I'm confused. What's the best way to do it?
Many thanks!
There is a difference, but it's not really the difference you may think.
In PHP5, "$db" holding an object is basically equivalent to a "Foo *" in C or C++. In other words, $db doesn't store the whole object, it just stores a small token that lets the code find the object when necessary. When you pass this token by value, it's as fast as passing an integer value rather than a copy of the entire object. But if you assign $db, it doesn't change the value in the caller because you're changing your local variable holding the token to contain a different token.
If the function takes "&$db", that's basically the equivalent of passing "Foo **" in C, or more correctly a function taking a "Foo *&" in C++. The call is just as fast since it's the same size thing that's being passed, but inside the function if you assign to $db it will change the value of $db in the caller because the "pass by reference" variable points you to the memory location holding the token in the caller.
The best way to do it is to pass by value (do not use "&") unless you know what you're doing and why you're doing it.
That's a good question.
You can always do a test by opening a $db handle, passing it to a function, and checking them via the === operator to make sure they are the same object.
This would be a good job for static methods. That is how many frameworks accomplish the same task.
class DB
{
private static $db = FALSE:
public static function init($dbConfig)
{
if(! self:$db)
{
self::$db = new Database($dbConfig);
}
}
public static function preparedSelect($sql, $params)
{
if(! self::$db)
{
die("call the init method first");
}
// db stuff, where you would call $this->db call self::$db
}
}
So in your other classes where you want to make calls to the database all you would have to do is:
class General
{
public function __construct()
{
DB::init($dbConfig);
}
public function someMethod()
{
$params = array('username' => $username);
$result = DB::preparedSelect('select password, salt from users where username = :username', $params);
}
}