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;
}
Related
Im relatively new to programming, with about 1 years part-time learning experience, im very new to PHP, only about a few weeks and using w3schools to help me
Im now trying to make the switch to OOP style and just cant understand the concept, or rather how and when to apply it and have thus turned here, where I have been a long time lurker instead of contributor for some help and advice.
I would like some help / short explanation how I would write the folloing in a PHP oop way
$sql="SELECT name, lastname, member_nr, joindate, order, creditCardInfo
from members
WHERE member_nr = $'member_nr'";
$result = mysql_query($sql) or die("error");
while($row = mysql_fetch_array){
echo '<h3>Personal Profile</h3>';
echo $name = $row['name'];
echo $lastName = $row['lastname'];
:
:
}
My problem is I dont know if I should create a class for the above, personal profile can be seen as a person right which is an object...? But do I include the HTML part and the mysql_query part etc in my class...Ive just got so many questions when it comes to OOP, its very hard to learn on your own thats why im really appreciate any drop of help or advice I can get on here
Thank you
First you should use mysqli, as all mysql_* are deprecated and are removed from PHP in the future.
Here a basis class with some functions, but you should expand it for your use! And learn what the functions do which got no comments on your own, to learn more.
This makes multiple connections to the database, so reading some stuff about singleton would be good for you too!
<?php
class dbconnection {
private $dbHostname;
private $dbName;
private $dbUsername;
private $dbUserpassword;
private $error;
private $querysuccess;
private $connected;
private $mysqli;
public function __construct() {
$this->dbHostname = 'localhost';
$this->dbName = 'databasename';
$this->dbUsername = 'username';
$this->dbUserpassword = 'password';
$this->connected = false;
}
public function __destruct() {
$this->mysqli->Close();
}
public function connect() {
//establishing a database connection
$this->mysqli = new mysqli($this->dbHostname, $this->dbUsername, $this->dbUserpassword, $this->dbName);
if($this->mysqli->connect_errno) {//When there was an error during the connecting
echo 'Connection Error:<br>'.$this->mysqli->connect_error;
$this->connected = false;
} else {
$this->connected = true;
}
if(!$this->mysqli->set_charset('utf8')) {//Need to be done for some functions!
echo 'Error during seting the charset: <br>'.$this->mysqli->error;
}
}
public function doquery($query_str) {
//method which executes the query
$returnval = false;
if($this->connected && $query_str != '') {
//only when connected AND the query is not empty
$res = $this->mysqli->query($query_str);//this is the equivalent of mysql_query
if($this->error_get() == '') {//Check for an error
$this->querysuccess = true;
} else {
$this->querysuccess = false;
}
$returnval = $res;
} else {
echo 'No database connection, this needs some!';
}
return $returnval;
}
public function query_success() {
return $this->querysuccess;
}
public function affected_rows_get() {
return $this->mysqli->affected_rows;
}
public function error_get() {
return $this->mysqli->error;
}
public function insert_id_get() {
return $this->mysqli->insert_id;
}
public function escape_str($str) {
return $this->mysqli->real_escape_string($str);
}
public function is_connected() {
return $this->connected;
}
public function fetch_assoc(&$res){
return $res->fetch_assoc();
}
public function fetch_assoc_array(&$res){
return $res->fetch_array(MYSQLI_ASSOC);
}
}
This case wouldn't be a good example. You want a class when you want to encapsulate logic of one entity to simplify its use outside the class.
For example:
class Member {
private $id, $name,
$lastname, $member_nr, $joindate, $order, $creditCardInfo;
public function __construct($id = 0) {
if($id != null) $this->loadFromDB();
}
private function loadFromDB() {
//Do db load here...
}
public function Update(){
//Do db update
}
public function Delete() {
//Do db delete...
}
public function GetFromMemberNR($nr) {
//Do select
}
//Additional Functions Verfication
}
In the end you'll have fairly complex code here. But to use it outside you just include the class's php file.
include 'member.php';
$member = new Member();
$member->GetFromMemberNR(2); //Does everything for you inside the function..
There are plenty of tools to help you do database operations easier, but that is the basis of OOP. The main idea is Encapsulation for reusability.
The Situation
I'm fairly new to object-oriented programming in PHP and currently I'm creating a small CMS for learning purposes. I've learned a lot about OOP on my way, but I'm facing a weird issue at the moment. I've created a Singleton class to deal with the database connection and queries.
public static function getInstance()
{
if(!isset(self::$instance))
{
self::$instance = new Database();
}
return self::$instance;
}
In the same class, there also is a method to execute queries. It takes two parameters, the query and an optional array with parameters to bind for the prepared statements. You can see its source below.
public function execute($query, $params = array())
{
$this->error = false; // Set 'error' to false at the start of each query.
if($this->query = $this->pdo->prepare($query))
{
if(!empty($params))
{
$index = 1;
foreach($params as $parameter)
{
$this->query->bindValue($index, $parameter);
++$index;
}
}
if($this->query->execute())
{
$this->results = $this->query->fetchAll(PDO::FETCH_OBJ);
$this->count = $this->query->rowCount();
}
else
{
$this->error = true;
}
}
return $this;
}
The Problem
If I have multiple queries on the same page, the results and count variables still contain the values of the first query. Imagine the following - the first query retrieves all users from my database. Let's say there are 15. The second query retrieves all blog posts from the database, let's say there are none. If no posts are present, I want to display a message, otherwise I run a loop to display all results. In this case, the loop is executed even though there are no blog posts, because the count variable is used to determine if there are posts in the database and it still holds the 15 from the first query somehow.
This obviously leads to some errors. Same with results. It still holds the value from the first query.
$query = Database::getInstance()->execute('SELECT * FROM articles ORDER BY article_id DESC');
if(!$query->countRes())
{
echo '<h2>There are no blog posts in the database.</h2>';
}
else
{
foreach($query->results() as $query)
{
echo '<article>
<h3>'.$query->article_heading.'</h3>
<p>'.$query->article_preview.'</p>
</article>';
}
}
The countRes() and results() methods simply return the variables from the DB class.
I hope that I have explained the problem understandable. Responses are very appreciated.
I would use a response object to avoid attaching query specific data to the global database object.
Example:
<?php
class PDO_Response {
protected $count;
protected $results;
protected $query;
protected $error;
protected $success = true;
public function __construct($query){
$this->query = $query;
try{
$this->query->execute();
}catch(PDOException $e){
$this->error = $e;
$this->success = false;
}
return $this;
}
public function getCount(){
if( is_null( $this->count ) ){
$this->count = $this->query->rowCount();
}
return $this->count;
}
public function getResults(){
if( is_null( $this->results ) ){
$this->results = $this->query->fetchAll(PDO::FETCH_OBJ);
}
return $this->results;
}
public function success(){
return $this->success;
}
public function getError(){
return $this->error;
}
}
Then in your database class:
public function execute($query, $params = array())
{
if($this -> _query = $this -> _pdo -> prepare($query))
{
if(!empty($params))
{
$index = 1;
foreach($params as $parameter)
{
$this -> _query -> bindValue($index, $parameter);
++$index;
}
}
return new PDO_Response($this->_query);
}
throw new Exception('Some error text here');
}
UPDATE: Moved execution into response class for error handling
Example usage (not tested)
$select = $database->execute('SELECT * FROM table');
if( $select->success() ){
//query succeeded - do what you want with the response
//SELECT
$results = $select->getResults();
}
$update = $database->execute('UPDATE table SET col = "value"');
if( $update->success() ){
//cool, the update worked
}
This will help fix your issue in the event that subsequent queries fail, there will not be any old query data attached to the database object.
I have been working on AMFPHP + codeigniter + flash and everything was working just fine but, when I created a stored procedure the problem started. I was able to call the stored procedure with multiple result sets from the AMF browser but whenever the function was called from the flash itself it raises the Bad Version error.
Below is the library {from CI forum} to traverse multiple result sets am using
class Mydb
{
private $CI, $Data, $mysqli, $ResultSet;
/**
* The constructor
*/
function __construct()
{
$this->CI =& get_instance();
$this->Data = '';
$this->ResultSet = array();
$this->mysqli = $this->CI->db->conn_id;
}
public function GetMultiResults($SqlCommand)
{
/* execute multi query */
if (mysqli_multi_query($this->mysqli, $SqlCommand)) {
$i=0;
do
{
if ($result = $this->mysqli->store_result())
{
while ($row = $result->fetch_assoc())
{
$this->Data[$i][] = $row;
}
mysqli_free_result($result);
}
$i++;
}
while ($this->mysqli->next_result());
}
return $this->Data;
}
}
and calling it like this:
$this->load->library('mydb');
$this->mydb->GetMultiResults("CALL test()");
I have noticed that the library loading line raises the Bad Version error at flash end as if I comment out this line it works {works like no error is ther but SP doesn't execute}
Any Idea on how to fix this strange issue.
Although CodeIgniter uses mysqli driver the next_result() method is not set in the DB_driver.
Here and here you can find further details. The idea is:
define next_result() method in system/database/DB_driver.php:
function next_result()
{
if (is_object($this->conn_id))
{
return mysqli_next_result($this->conn_id);
}
}
(be sure to push this up to your notes pile for the CI system core upgrade )
make sure you are using mysqli drive (application/config/database.php)
In your model after you call your stored procedure and BETWEEN each fetch of results use $query_or_somethig-else->next_result(); (and use $query_or_somethig-else->free_result(); in the final)
I have been working on multiple query execution in store procedure in codeigniter
I created a library named SP.php. Here is the code also change in config to database =
mysqli
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class CI_SP {
private $CI;
function __construct() {
$this->CI = & get_instance();
}
public function GetResults($SqlCommand) {
$k = 0;
$arr_results_sets = array();
/* execute multi query */
if (mysqli_multi_query($this->CI->db->conn_id, $SqlCommand)) {
do {
$result = mysqli_store_result($this->CI->db->conn_id);
if ($result) {
$l = 0;
while ($row = $result->fetch_assoc()) {
$arr_results_sets[$k][$l] = $row;
$l++;
}
}
$k++;
} while (mysqli_next_result($this->CI->db->conn_id));
return $arr_results_sets;
}
}
}
and the model code is
$result = $this->sp->GetResults("call function(parameters);
$result1 = $this->sp->GetResults("call function(parameters));
print_r($result);
print_r($result1);
exit;
return $query->result_array();
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.
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.