MySQL access classes in PHP - php

I have a connection class for MySQL that looks like this:
class MySQLConnect
{
private $connection;
private static $instances = 0;
function __construct()
{
if(MySQLConnect::$instances == 0)
{
//Connect to MySQL server
$this->connection = mysql_connect(MySQLConfig::HOST, MySQLConfig::USER, MySQLConfig::PASS)
or die("Error: Unable to connect to the MySQL Server.");
MySQLConnect::$instances = 1;
}
else
{
$msg = "Close the existing instance of the MySQLConnector class.";
die($msg);
}
}
public function singleQuery($query, $databasename)
{
mysql_select_db(MySQLConfig::DB, $this->connection)
or die("Error: Could not select database " . MySQLConfig::DB . " from the server.");
$result = mysql_query($query) or die('Query failed.');
return $result;
}
public function createResultSet($query, $databasename)
{
$rs = new MySQLResultSet($query, MySQLConfig::DB, $this->connection ) ;
return $rs;
}
public function close()
{
MySQLConnect::$instances = 0;
if(isset($this->connection) ) {
mysql_close($this->connection) ;
unset($this->connection) ;
}
}
public function __destruct()
{
$this->close();
}
}
The MySQLResultSet class looks like this:
class MySQLResultSet implements Iterator
{
private $query;
private $databasename;
private $connection;
private $result;
private $currentRow;
private $key = 0;
private $valid;
public function __construct($query, $databasename, $connection)
{
$this->query = $query;
//Select the database
$selectedDatabase = mysql_select_db($databasename, $connection)
or die("Error: Could not select database " . $this->dbname . " from the server.");
$this->result = mysql_query($this->query) or die('Query failed.');
$this->rewind();
}
public function getResult()
{
return $this->result;
}
// public function getRow()
// {
// return mysql_fetch_row($this->result);
// }
public function getNumberRows()
{
return mysql_num_rows($this->result);
}
//current() returns the current row
public function current()
{
return $this->currentRow;
}
//key() returns the current index
public function key()
{
return $this->key;
}
//next() moves forward one index
public function next()
{
if($this->currentRow = mysql_fetch_array($this->result) ) {
$this->valid = true;
$this->key++;
}else{
$this->valid = false;
}
}
//rewind() moves to the starting index
public function rewind()
{
$this->key = 0;
if(mysql_num_rows($this->result) > 0)
{
if(mysql_data_seek($this->result, 0) )
{
$this->valid = true;
$this->key = 0;
$this->currentRow = mysql_fetch_array($this->result);
}
}
else
{
$this->valid = false;
}
}
//valid returns 1 if the current position is a valid array index
//and 0 if it is not valid
public function valid()
{
return $this->valid;
}
}
The following class is an example of how I am accessing the database:
class ImageCount
{
public function getCount()
{
$mysqlConnector = new MySQLConnect();
$query = "SELECT * FROM images;";
$resultSet = $mysqlConnector->createResultSet($query, MySQLConfig::DB);
$mysqlConnector->close();
return $resultSet->getNumberRows();
}
}
I use the ImageCount class like this:
if(!ImageCount::getCount())
{
//Do something
}
Question: Is this an okay way to access the database? Could anybody recommend an alternative method if it is bad?
Thank-you.

Hey Mike, there's nothing wrong with implementing your own classes to handle database connection, what you have so far is fine, however PHP already provides an interface for handling DB connections regardless of the database manager you are connecting to. I'd recommend you to take a look at it http://www.php.net/manual/en/book.pdo.php since it has mostly all the functionality needed for handling queries, statements, resultsets, errors, and so forth.
Cheers,
M.

I'm not sure that having a class called "ImageCount" is really necessary. If you're going to be working with images - I would simply have a class called "Image" with a static function to get the count of all images, and some other functions to deal with images.
Also, if you try to create a new instance when one exists - how about returning the existing instance instead of using die() to stop the program.

Related

If I cant eliminate circular references, then they should be in one class?

a SQL implementation:
abstract class SQL
{
abstract public function connect();
abstract public function query($sql);
abstract public function queryAndReturn($sql);
abstract public function startTransaction();
abstract public function commit();
abstract public function rollback();
}
class MySQL extends SQL
{
public function connect()
{
mysql_connect (....)
}
public function query($sql)
{
return mysql_query($sql);
}
public function queryAndReturn()
{
$result = $this->query($sql);
$results = [];
whilte ($item = mysql_fetch_assoc($result))
{
$results[] = $item;
}
return $results;
}
public function startTransaction()
{
return $this->query('START TRANSACTION');
}
public function commit()
{
return $this->query('COMMIT');
}
public function rollback()
{
return $this->query('ROLLBACK');
}
public function runAtomicFunction (\Closure $function)
{
try
{
$this->query('SET autocommit=0');
$this->startTransaction();
$function();
$this->commit();
}
catch (Exception $e)
{
$this->rollback();
}
}
}
the last 4 methods is something like "transaction" so lets move them to another class:
class MySQL extends SQL
{
public function connect()
{
mysql_connect (....)
}
public function query($sql)
{
return mysql_query($sql);
}
public function queryAndReturn()
{
$result = $this->query($sql);
$results = [];
whilte ($item = mysql_fetch_assoc($result))
{
$results[] = $item;
}
return $results;
}
public function getNewTransaction()
{
return new Transaction($this);
}
}
class Transaction
{
private $db;
public function __construct(Sql $db)
{
$this->db = $db;
}
public function startTransaction()
{
return $this->db->query('START TRANSACTION');
}
public function commit()
{
return $this->db->query('COMMIT');
}
public function rollback()
{
return $this->db->query('ROLLBACK');
}
public function runAtomicFunction (\Closure $function)
{
try
{
$this->db->query('SET autocommit=0');
$this->db->startTransaction();
$function();
$this->db->commit();
}
catch (Exception $e)
{
$this->db->rollback();
}
}
}
$sql = new MySQL();
$t = $sql->getNewTransaction();
$t->runAtomicFunction(...);
this is all good, but this is when circular references enter. Sql depends on Transaction and vice versa. Is this a sign that I must not separate the transaction?
If I cant eliminate circular references, then they should be in one class?
What benefit would it be to split them up?
I'd leave them in a single class unless you can come up with a really good reason to split them.

php Fatal error: Class '' not found in..doesnt specify the class

I'm getting a class not found error but without the name of the class. I got the code from here
but when I try to run it, it gives the following error..
Fatal error: Class '' not found in C:\Program Files\Apache Software Foundation\Apache24\Apache24\htdocs\framework\library\controller.class.php on line 16
and the following is the controller
<?php
class Controller {
protected $_model;
protected $_controller;
protected $_action;
protected $_template;
function __construct($model, $controller, $action) {
$this->_controller = $controller;
$this->_action = $action;
$this->_model = $model;
include 'model.class.php';//other similar posts suggested this but its not working
$this->$model = new $model;
$this->_template = new Template($controller,$action);
}
function set($name,$value) {
$this->_template->set($name,$value);
}
function __destruct() {
$this->_template->render();
}
}
I'm assuming its the model class which is not being found. The model class code is
<?php
class Model extends SQLQuery {
protected $_model;
function __construct() {
$this->connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$this->_model = get_class($this);
$this->_table = strtolower($this->_model)."s";
}
function __destruct() {
}
}
and sqlquery class is
<?php
class SQLQuery {
protected $_dbHandle;
protected $_result;
/** Connects to database **/
function connect($address, $account, $pwd, $name) {
$this->_dbHandle = #mysql_connect($address, $account, $pwd);
if ($this->_dbHandle != 0) {
if (mysql_select_db($name, $this->_dbHandle)) {
return 1;
}
else {
return 0;
}
}
else {
return 0;
}
}
/** Disconnects from database **/
function disconnect() {
if (#mysql_close($this->_dbHandle) != 0) {
return 1;
} else {
return 0;
}
}
function selectAll() {
$query = 'select * from `'.$this->_table.'`';
return $this->query($query);
}
function select($id) {
$query = 'select * from `'.$this->_table.'` where `id` = \''.mysql_real_escape_string($id).'\'';
return $this->query($query, 1);
}
/** Custom SQL Query **/
function query($query, $singleResult = 0) {
$this->_result = mysql_query($query, $this->_dbHandle);
if (preg_match("/select/i",$query)) {
$result = array();
$table = array();
$field = array();
$tempResults = array();
$numOfFields = mysql_num_fields($this->_result);
for ($i = 0; $i < $numOfFields; ++$i) {
array_push($table,mysql_field_table($this->_result, $i));
array_push($field,mysql_field_name($this->_result, $i));
}
while ($row = mysql_fetch_row($this->_result)) {
for ($i = 0;$i < $numOfFields; ++$i) {
$table[$i] = trim(ucfirst($table[$i]),"s");
$tempResults[$table[$i]][$field[$i]] = $row[$i];
}
if ($singleResult == 1) {
mysql_free_result($this->_result);
return $tempResults;
}
array_push($result,$tempResults);
}
mysql_free_result($this->_result);
return($result);
}
}
/** Get number of rows **/
function getNumRows() {
return mysql_num_rows($this->_result);
}
/** Free resources allocated by a query **/
function freeResult() {
mysql_free_result($this->_result);
}
/** Get error string **/
function getError() {
return mysql_error($this->_dbHandle);
}
}
I'm new to PHP and I'm using PHP 5.5.15. I know I should probably switch this to pdo, but i just want to get this working before gettin jiggy with it.
Any help much appreciated
Simple said, you have this function for your controller:
function __construct($model, $controller, $action) {
$this->$model = new $model;
}
You need to give a $model, wich would be the name of a class. You give no name. This is why class "" can not be found.
If we would write this:
$controller = new Controller("mycrazymodel", null, null);
It means:
function __construct($model, $controller, $action) {
//$this->$model = new $model;
$this->$model = new mycrazymodel; //above means this, if $model = "mycrazymodel"
}
So what does this mean for you?
Locate the call of the Controller::__construct method, which typical mean new Controller(...) and make sure, you give the classname as $model parameter.
Take a look at the manual for further information: http://php.net/manual/en/language.namespaces.dynamic.php

PHP Design Pattern for using instantiated classes

We are trying to understand the best way to use mysqli/other classes in multiple custom classes so that we don't instantiate a new object every time.
Is the code below the best/correct way of doing this?
The functions are only examples.
Thank you :)
<?php
class Base {
public function __get($name) {
if($name == 'db'){
$db = new mysqli('**', '*s', '*', '*');
$this->db = $db;
return $db;
}
if($name == 'blowfish'){
$blowfish = new PasswordHash(8, true);
$this->blowfish = $blowfish;
return $blowfish;
}
}
}
class A extends Base {
public function validate($username, $password) {
$query = $this->db->query("SELECT * FROM users");
return $query->num_rows;
}
public function password($password)
{
return $this->blowfish->HashPassword($password);
}
}
class PasswordHash {
public function __construct($iteration_count_log2, $portable_hashes) { }
public function HashPassword($password) {
return $password;
}
}
$a = new A;
echo $a->validate('test','test'); // returns number rows count as expected
echo $a->password('password123'); // returns password123 as expected
?>
You are/should probably be more interested in Dependency Injection instead of creating a tight coupling of Base|A and the MySQL database.

Can't write/read from database

I am trying to make a 1 on 1 chat website by learning as I progress, but I've come to a hault.
I can't write to the database.
I have four php files linked below.
Index
Init:
session_start();
define('LOGGED_IN', true);
require 'classes/Core.php';
require 'classes/Chat.php';
?>
Chat
Core:
class Core {
protected $db, $result;
private $rows;
public function __construct() {
$this->db = new mysqli("localhost","root","");
}
public function query($sql) {
$this->result = $this->db->query($sql);
}
public function rows() {
for($x = 1; $x <= $this->db->affected_rows; $x++) {
$this->rows[] = $this->result->fetch_assoc();
}
return $this->rows;
}
}
?>
I have a MySql database set with WAMP.
P.S. Yes, I have opened the "< ? php"
but it doesn't get displayed here.
From what I have seen you do not select a default database. You must either give a default database in
$this->db = new mysqli("localhost","root","", "mydatabase");
or select one later with
$this->db->select_db("mydatabase");
You also don't check the return values of the mysql calls. For example, add
public function query($sql) {
$this->result = $this->db->query($sql);
if ($this->result === false) {
echo $this->db->error;
}
}
after your mysql statements, in order to see whether the statements succeed or fail.
For debugging purposes you can display the sql and corresponding result
public function query($sql) {
var_dump($sql);
$this->result = $this->db->query($sql);
var_dump($this->result);
echo $this->db->error;
}

Too many open MySQL connections

I am developing a project in which two portions of webpage frequently change and fetch recent data. I have some confusion about whether to use mysql_connect or mysql_pconnect? I have one config file that is being included in every page. There is one database connection object which I use for queries. Even when approximately 70 users are online it shows 20,000 connections on my server. Please suggest me the best way to keep a single connection alive from a single user, so there should be 70 connections when there are 70 users online. Currently I'm not using mysql_close method to close connection. Is this the reason it shows these many connections? Your advice will really be appreciated.
A common pattern used in this case is the singleton pattern, here's some rough code.
class DB_Instance
{
private static $db;
public static function getDB()
{
if (!self::$db)
self::$db = new Database();
return self::$db;
}
}
function getSomething()
{
$conn = DB_Instance::getDB();
.
.
.
}
Some examples/references
http://tutorialpedia.org/tutorials/Singleton+pattern+in+PHP.html
http://www.ricocheting.com/static/code/php/mysql-v3/Database.singleton.phps
http://netlinxinc.com/netlinx-blog/53-php/7-applying-the-singleton-pattern-to-database-connections-in-php.html
Here you have my implementation maybe it is useful for you
<?php
class Utils_Sql{
private $count = 0;
private static $sqlObj = null;
/**
* #return Utils_Sql
*/
public static function getSql(){
if(self::$sqlObj===null){self::$sqlObj = new Utils_Sql();}
return self::$sqlObj;
}
private $db;
private function __construct(){
$this->db = mysql_connect(MYSQL_SERVER,DB_LOGIN,DB_PASS);
if($this->db === false){
Utils_Logging_Logger::getLogger()->log(
array("Unable to connect to DB on Mysql_Server:".MYSQL_SERVER." with login:".DB_LOGIN." and pass:".DB_PASS."!")
,Utils_Logging_Logger::TYPE_ERROR
);
}else{
if (!mysql_select_db ( DB_NAME , $this->db )) {
$sql = "CREATE DATABASE " . DB_NAME;
$this->qry($sql);
if (!mysql_select_db ( DB_NAME , $this->db )) {
Utils_Logging_Logger::getLogger()->log(
array("DB: ".DB_NAME." not found"),
Utils_Logging_Logger::TYPE_ERROR
);
}
}
}
mysql_set_charset ('utf8',$this->getConnection());
}
public function getConnection(){return $this->db;}
public function qry($sql,$errType,$errMsg=""){
$this->count++;
// Utils_Logging_Logger::getLogger()->log("<br>$sql<br>",Utils_Logging_Logger::TYPE_LOG);
$ret = mysql_query($sql,$this->getConnection());
if(mysql_error($this->getConnection())){
//Error
$msgs = array(
"mysql_error: (".mysql_error($this->getConnection()).")",
"qry: \"$sql\""
);
if($errMsg!==""){$msgs[]="$errMsg";}
Utils_Logging_Logger::getLogger()->log($msgs,$errType);
}
return $ret;
}
public function getData($sql,$errType=Utils_Logging_Logger::TYPE_ERROR){
$r = $this->qry($sql,$errType);
if($r === false){
Utils_Logging_Logger::getLogger()->log("No Sql Resource, Illegal Query!",$errType);
return false;
}
$ret = array();
while(($data = mysql_fetch_assoc($r))!==false){
$ret[] = $data;
}
if(count($ret)===1){return $ret[0];}
else if(count($ret)>1){return $ret;}
else{
$msgs = array(
"No resulset found.",
"qry: \"$sql\""
);
Utils_Logging_Logger::getLogger()->log($msgs,$errType|Utils_Logging_Logger::TYPE_WARNING);
return false;
}
}
public function getInsertId($sql,$errType=Utils_Logging_Logger::TYPE_ERROR){
$this->qry($sql,$errType);
$ret = mysql_insert_id($this->getConnection());
if(!is_numeric($ret)){Utils_Logging_Logger::getLogger()->log("mysql_insert_id is not numeric!",$errType);}
return $ret;
}
public function getDbName(){return DB_NAME;}
public function __destruct(){
// Utils_Logging_Logger::getLogger()->log("Querys count: '$this->count'",Utils_Logging_Logger::TYPE_LOG);
}
}
Interstellar_Coder is correct, you want to use a singleton/factory solution for your db connection handling. We use here at work and it serves us well.
While Interstallar_Coder's solution is valid, I wrote up a more flexible solution in response to another post.
Destroy db connections:
public function __destruct()
{
foreach (self::$dbos as $key => $dbo) {
self::$dbos[$key] = null;
}
}
More info about PDO connection management.

Categories