Object oriented CRUD with Mysqli - php

I'm trying to learn OOP programming in PHP. So far i got couple of basic things but i don't know how to echo my results into the page. I made up Database class and Category class i wanna echo the results from read function but i don't know how to do that. Can someone help me refactor this so i can use both classes?
This is my code
class Database {
private $_connection;
private $_host = "localhost";
private $_username = "root";
private $_password = "";
private $_database = "cmsi";
// Conect to database is private and can only be used by getConection function result is returned object of mysqli class
//can be seen in var_dump() function
private function conect() {
//$this refers to class Database and her functions and propertys are being acsessed via -> sign
$this->_connection = new mysqli($this->_host, $this->_username,
$this->_password, $this->_database);
// Error handling
if(mysqli_connect_error()) {
trigger_error("Failed to conencto to MySQL: " . mysql_connect_error(),
E_USER_ERROR);
}
return $this->_connection;
}
//Safest way to iniate conection
public function getConection(){
return $this -> conect();
}
}
class Category{
private $db_sql;
public function __construct($db){
$this->db_sql = $db;
}
public function read(){
$conection = $this->db_sql;
$query = "Select * from category";
$result = $conection -> query($query);
return $result;
}
}
$db = new Database();
$conection = $db->getConection();
$obj = new Category($conection);
$obj->read();

You're almost there. Just store the result set in a variable and loop through it, like this:
// your code
$db = new Database();
$conection = $db->getConection();
$obj = new Category($conection);
// store the result set
$result_set = $obj->read();
// loop through the result set
while($row = $result_set->fetch_array()){
// your code
}

Related

Using class database connection in other class

I have a class with a connection to a database
$db = new db();
class db {
public $server = 'localhost';
public $user = '';
public $passwd = '******';
public $db = '';
public $dbCon;
function __construct() {
$this->dbCon = mysqli_connect($this->server, $this->user, $this->passwd, $this->db);
}
function __destruct() {
mysqli_close($this->dbCon);
}
}
Now i want to make an other class and using the connection like this:
class Categories (
function GetCategory($cat) {
$myQuery = "SELECT * FROM test GROUP BY $cat";
$results = mysqli_query($this->dbCon, $myQuery);
return $results;
}
)
How can i use the connection in a other class?
Can somebody help me out whit this?
Make the $dbCon in your db class a static variable, so you can access it from category's using db::$dbcon as the connection variable. You could also make a static function returning the static dbcon variable, usefull tot check if it is actually a link and not null.
This is just one solution of many possibilities, but probably the easiest to implement because it isn't likely you need more connections to a db, so a static is perfect for it.
A static is nothing more then a variable living in the namespace it is defined in, you don't need to initialize the class in order to access it. It's value is shared across all instances of the object, so creating multiple DB class instances allows you tot just return a static if it was set in a previous DB class instance.
class db{
static $link;
static function connect(){
if(self::$link = mysqli_connect(....)){
return self::$link;
} else {
die('could not connect to db');
}
}
static function getcon(){
return isset(self::$link) ? self::$link : self::connect();
}
}
class Categories{
function GetCategory($cat){
$myQuery = "SELECT * FROM test GROUP BY $cat";
return mysqli_query(db::getcon(), $myQuery);
}
}
Create an object of the db class in the categories class. Then use that object to query the db accordingly. Also make sure you use a static variable in the db class. SO that the connection variable is created once and will be used all along the application.
Your db class may look like this
class db {
public $server = 'localhost';
public $user = '';
public $passwd = '******';
public $db = '';
public static $dbCon;
function __construct() {
$this->dbCon = mysqli_connect($this->server, $this->user, $this->passwd, $this->db);
}
function __destruct() {
mysqli_close($this->dbCon);
}
}
Your categories class may look like this
class Categories {
$connection=db::$dbCon;
if(!$connection){
$db=new db();
$connection=db::$dbCon;
}
function GetCategory($cat) {
$myQuery = "SELECT * FROM test GROUP BY $cat";
$results = mysqli_query($this->connection, $myQuery);
return $results;
}
}

PHP OOP: How do I create a database class?

Currently, my website runs procedural PHP. I would like to achieve to have a database class that can be used for other classes.
STATUS QUO:
On every page I include my dp.php before my header.php, the content and footer.php appear. My db.php looks like this:
// Credentials
$dbhost = "localhost";
$dbname = "dbname";
$dbuser = "dbuser";
$dbpass = "dbpassword";
// Connection
global $db;
$db = new mysqli();
$db->connect($dbhost, $dbuser, $dbpass, $dbname);
$db->set_charset("utf8");
// Check Connection
if ($db->connect_errno) {
printf("Connect failed: %s\n", $db->connect_error);
exit();
}
GOAL:
Having a database object that I can integrate into the EventData class that I have been building. The desired function of this class is that it will allow me to easily access data of my events table on any page. My EventData-class.php looks like this:
Class EventData {
private $_db;
private $_event_id;
public function __construct($eventID) {
$this -> _event_id = $eventID;
}
public function getValue($fieldname) {
// Build query for getting event details
$query = 'SELECT * FROM events WHERE id=' . $this -> _event_id . '';
// Do Search
$results = $db->query($query);
// Store all event details available in variables
while ($result = $results->fetch_assoc()) {
$value = $result[$fieldname];
}
// Return value
return $value;
}
}
I am new to OOP and am interested in learning how I need to modify both db.php and EventData-class.php in order to work.
The answer is brief and needs some your effort to improve or encode the idea.
First of all create a collection of items, something like this
class EventCollection {
protected $items = array(); // I keep protected so only addItem, removeItem etc. can be used to handle data
public $database = NULL;
public function addItem(EventData $item){
$this->items[] = $item;
$item->collection = $this; // this allows your EventData object to refer to its container
}
public function clear(){
$this->items = array();
}
public function __construct(mysqli $datb){ // inject mysqli object
$this->database = $datb;
}
public function removeItem... etc.
}
Having prepared the collection class, just update your EventData (consider creating a child class) by $collection field:
class EventData {
private $_db; // throw this away, not necessary
private $_event_id;
public $collection = NULL;
// etc.
Then in your main code create a $db variable as you do. Then create a (empty) collection:
$myEventCollection = new EventCollection($db);
and add items by
$myEvent = ....;
$myEventCollection->add($myEvent);
To refer to $db value inside the EventData class use something like this
class EventClass { ....
public function updateEvent(){
$this->collection->database->query('UPDATE ...');

How to properly use dependency injection with PHP?

I'm very new at PHP. I have two classes: Database and RetrieveItem. Because RetrieveItem needs a connection, I've just been extending the Database class to use its constructor. Apparently this is wrong, because RetrieveItem is not a database?
Here is my current code:
class Database {
public $host = '127.0.0.1';
public $username = 'root';
public $password = '';
public $dbname = 'example';
function __construct(){
$this->connect = new PDO("mysql:host=$this->host;dbname=$this->dbname", $this->username, $this->password);
}
}
class RetrieveItem extends Database {
function retrieve_item(){
$query = $this->connect->prepare("SELECT * FROM posts");
$query->execute();
$all_items = $query->fetchAll(PDO::FETCH_ASSOC);
return $all_items;
}
}
And on a separate page, to use this, I have:
include 'db.php';
$retrieve = new RetrieveItem();
print_r($retrieve->retrieve_item());
Rather than extend the class, how can I access the Database constructor in the cleanest possible way?
Any help or guidance would be much appreciated.
This amended code is still not working:
Argument 1 passed to RetrieveItem::__construct() must be an instance of Database, none given:
class Database {
public $host = '127.0.0.1';
public $username = 'root';
public $password = '';
public $dbname = 'example';
function __construct(){
$this->connect = new PDO("mysql:host=$this->host;dbname=$this->dbname", $this->username, $this->password);
}
}
class RetrieveItem {
private $_db;
public function __construct(Database $database){
$this->_db = $database;
}
public function retrieve_item(){
$query = $this->connect->prepare("SELECT * FROM posts");
$query->execute();
$all_items = $query->fetchAll(PDO::FETCH_ASSOC);
return $all_items;
}
}
In use:
include 'db.php';
$database = new Database();
$retrieve = new RetrieveItem($database);
print_r($retrieve->retrieve_item());
As you said, with plain dependency injection
class RetrieveItem {
private $_db;
public function __construct(Database $db) {
$this->_db = $db;
}
}
For easier use, you can abstract the injection in container, or, at least, has one super class that recieves the injection.
A dependency injection is so easy but it sounds complicated.
$class1 = new firstclass();
$class2 = new secondclass($class1); //This is a dependency injection.
class firstclass{
private $var1;
private $var2;
public function __construct(){
$this->var1 = "hello";
$this->var2 = "world";
}
public function getvar1(){
return $this->var1;
} //imagine a second one like this for var2;
}
class secondclass{
private $fc; //will hold first class object or the dependency.
public function __construct($firstclassobject){
$this->fc = $firstclassobject;
echo $this->fc->getvar1(); //call dependency methods like this.
echo $this->fc->getvar2();
} //echoes helloworld
}
So you pretty much put an object of one class and asign it to a field in your other class.
for your edit
set this line in your database class at the top.
public connect; //add to dbclass
Then do this in your function
public function retrieve_item(){
$connect = $this->db->connect; //added this
$query = $connect->prepare("SELECT * FROM posts"); //changed this
$query->execute();
$all_items = $query->fetchAll(PDO::FETCH_ASSOC);
return $all_items;
}
class Database {
public $host = '127.0.0.1';
public $username = 'root';
public $password = '';
public $dbname = 'example';
public $connect;
function __construct(){
$this->connect = new PDO("mysql:host=$this->host;dbname=$this->dbname", $this->username, $this->password);
}
}
class RetrieveItem {
private $connect;
public function __construct(&$db){
$this -> connect = $db -> connect;
}
function retrieve_item(){
$query = $this->connect->prepare("SELECT * FROM posts");
$query->execute();
$all_items = $query->fetchAll(PDO::FETCH_ASSOC);
return $all_items;
}
}
// Usage
$db = new Database();
$retrieve_item = new RetrieveItem($db);
Here in Retrieve Item we tried to send the database object as a refereneced variable rather sending a copy of its, which happens to be a good way of passing connection to your operable classes

Cant get results out database oophp, mysqli

im trying to understand oophp a litle bit but now im stuck in getting information out of my database. What am i doing wrong? After the tip off PDO I tried the following but also no results...
index.php
<?php
include('classes/database.class.php');
$db = new Database();
$db->connect();
$res = $db->select();
print_r($res);
?>
database.class.php
<?php
class Database {
private $db_host = 'localhost'; // Database Host
private $db_user = 'root'; // Gebruikersnaam
private $db_pass = 'root'; // Passwoord
private $db_name = 'quickscans'; // Database naam
public function connect()
{
try
{
$db = new PDO('mysql:host='.$this->db_host.';dbname='.$this->db_name,$this->db_user,$this->db_pass);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function disconnect()
{
$db = null;
}
public function select()
{
$sql = 'SELECT id FROM bedrijf';
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['id'].'<br>';
}
}
}
?>
Maybe this code is a bit cleaner.. but still no results :(.
You aren't assigning any instance variables in this class.
The query method has no access to the connection you create because the object has no state.
Your constructor for the class should create the connection, and then queries can be called on this property.
class Database {
private $db_host = 'localhost'; // Database Host
private $db_user = 'root'; // Gebruikersnaam
private $db_pass = 'root'; // Passwoord
private $db_name = 'quickscans'; // Database naam
public function __construct(){
$this->connect();
}
public function connect()
{
try
{
$this->connection = new PDO('mysql:host='.$this->db_host.';dbname='.$this->db_name,$this->db_user,$this->db_pass);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function disconnect()
{
$this->connection = null;
}
public function select()
{
$sql = 'SELECT id FROM bedrijf';
$results = $this->connection->query($sql);
foreach($results as $row)
{
echo $row['id'].'<br>';
}
}
}
The $this keyword sets instance variables for the class, so the connection property becomes a PDO instance that other methods can act upon. Without this, the varibles created in the methods, in this case $db are just orphaned in the local function scope and not accessible in the greater class.
Utilizing this approach elminates the need to run connect() in the calling context. You don't need to use the constructor to do this if you don't want to, you'll just always need to connect first in order to create the connection property and have it available to the rest of the class. Also note you can name the property whatever you like, I just used connection because it made the most sense in the API.
Also, as commented, to make this a bit more usable you should have the select method return the query results array rather than having it output directly.
public function select()
{
$sql = 'SELECT id FROM bedrijf';
$results = $this->connection->query($sql);
if(!empty($results)){
return $results
}else{
return false;
}
}

Start work with PHP OOP

I now learn PHP OOP and I want to get yours tips. I create DB connection class, is this okay?
How use "Database" class in another class? Always use "extends"?
Thanks
<?php
//Config
$db_user = 'root';
$db_pass = '';
$db_host = 'localhost';
$db_name = 'test';
class Database
{
private $Database;
private static $instance;
public static function instance()
{
if ( !self::$instance )
self::$instance = new Database();
return self::$instance;
}
public function connect($host, $user, $password, $name)
{
$this->db_link = mysql_connect($host, $user, $password);
mysql_set_charset('utf8');
mysql_select_db($name, $this->db_link);
}
public function query($query)
{
$sql = mysql_query($query);
$row = mysql_fetch_array($sql);
return $row;
}
}
class Book extends Database
{
public function getData2()
{
$sql = $this->query('SELECT * FROM users WHERE price = "7"');
return $sql['name'];
}
}
$db = Database::instance();
$db->connect($db_host, $db_user, $db_pass, $db_name);
$b = new Book();
$res = $b->getData2();
print_r($res);
?>
You can extends the database class but it is not what I suggest.
You could also use the keyword global inside the function where you actually need database to let the function get the database instance from outside; but still some people get nervous about global keyword.
You could pass the instance of the database class as argument of constructor of the class where you need database, in this way you will be able to call db methods with a simple chain: $this->db->connect();
As björn states, a book is not a database, wouldn't recommend extend.
One approach would be to on object initialization of book, pass the reference to the db-layer/object..
$myDb = new dbLayer($settings);
$myBook = new book($myDb);
$a = $myBook->getAllData($someParameter);
in the constructor of book you save the reference to the dblayer...
class book {
var $dbTier;
__constructor($db) {
$this->dbTier = $db;
...
regards,
//t
You can do something like this, this should be easy to understand
class User{
private $db;
public function __construct($db){
$this->db = $db;
}
}
The $db in the constructor parameter would be your database connection and required fom another file. All any how you get to it but not in the class.
require 'file from where you have your database';
$user = new User($db);
Anytime you like to user the database to make a query, you just reference it like below
$this->db->query();
You would not use extends here ideally unless Book is a subclass of Database. You would do something like:
class Book
{
var $db;
function __construct() {
$this->db = Database::instance();
}
}
Then the book class would use the instance of the database object and you can always access it with $this->db inside Book.

Categories