Do I need to Instantiate Php Database class for every query? - php

I have a php database class for managing all my database queries:
class DatabaseConnection()
{
private $link;
public $filter;
public function log_db_errors( $error, $query )
{
if( MY_DEBUG )
{
echo $message;
}
}
public function __construct()
{
global $connection;
mb_internal_encoding( 'UTF-8' );
mb_regex_encoding( 'UTF-8' );
$this->link = new mysqli( MY_HOST, MY_USER, MY_PASS, MY_DB );
$this->link->set_charset( "utf8" );
if( $this->link->connect_errno )
{
$this->log_db_errors( "Connect failed", $this->link->connect_error );
echo 'Server error. Please try again sometime. DB';
exit();
}
}
public function __destruct()
{
$this->disconnect();
}
public function filter( $data )
{
if( !is_array( $data ) )
{
$data = trim( htmlentities( $data ) );
$data = $this->link->real_escape_string( $data );
}
else
{
$data = array_map( array( 'DB', 'filter' ), $data );
}
return $data;
}
public function query( $query )
{
$full_query = $this->link->query( $query );
if( $this->link->error )
{
$this->log_db_errors( $this->link->error, $query );
$full_query->free();
return false;
}
else
{
$full_query->free();
return true;
}
}
public function my_table_exists_create( $table, $variables = array() ) {
$check = $this->link->query("SELECT * FROM '$table' LIMIT 1");
if( $check ) return true;
else {
if( empty( $variables ) ) {
return false;
exit;
}
$sql = "CREATE TABLE IF NOT EXISTS ". $table;
$fields = array();
$values = array();
foreach( $variables as $field ) {
$fields[] = $field; //$values[] = "'".$value."'";
}
$fields = ' (' . implode(', ', $fields) . ')';
$sql .= $fields;
$query = $this->link->query( $sql );
if( $this->link->error ) {
$this->log_db_errors( $this->link->error, $sql );
return false;
}
else return true;
}
}
public function my_num_rows( $query )
{
$num_rows = $this->link->query( $query );
if( $this->link->error )
{
$this->log_db_errors( $this->link->error, $query );
return $this->link->error;
}
else
{
return $num_rows->num_rows;
}
}
public function exists( $table = '', $check_val = '', $params = array() )
{
if( empty($table) || empty($check_val) || empty($params) )
{
return false;
exit;
}
$check = array();
foreach( $params as $field => $value )
{
if( !empty( $field ) && !empty( $value ) )
{
if( $this->db_common( $value ) )
{
$check[] = "$field = $value";
}
else
{
$check[] = "$field = '$value'";
}
}
}
$check = implode(' AND ', $check);
$rs_check = "SELECT $check_val FROM ".$table." WHERE $check";
$number = $this->my_num_rows( $rs_check );
if( $number === 0 )
{
return false;
}
else
{
return true;
}
exit;
}
public function disconnect()
{
$this->link->close();
}
}
I use this class to manage all my queries, like insert to the database :
$database = new DatabaseConnection();
$Item_Details = array(
'item_title' => trim($_POST['title']),
'item_content' => trim($_POST['content']),
'item_updated' => date('Y-m-d H:i:s'),
'item_updatedby' => $my_loginid,
);
$where_clause = array('itemid' => $itemid);
$updated = $database->as_update( 'my_item', $Item_Details , $where_clause, 1 );
Now I need to know I can use this class without having a lot of connections that can slow down connection to the server which leads to timeout and having too many connection. I thought I could use a global variable
function my_constant_initialize()
{
global $databasecon;
$databasecon = new DatabaseConnection();
return $databasecon;
}
So please advice how to avoid too many connections. Also as well as tell whether it is necessary to instanciate the database class for every query or I can just call it once because I have used a lot of Include and require functions in my php code.

Reaching the MySQL database connection limit is hard in OOP PHP because it destructs the connection object if the script is finished. Just to be safe, have a destruct function in your class and unset the object at the end of the script. If you are really worried about reaching the connection cap you can go into MySQL and modify the max_connection_limit from I think 1000 to higher and increase the buffer pool.
Additionally you might look into switching languages to like Java which has a technique called "connection pooling." Works better than PHP's version. No this is not the same as p_connect or whatever it is in PHP.

At least you don't have to initiate the connection every time you are calling your class.
To see how you could use your database class without having to instantiate it every time, we would need to see some more of your code. The already mentioned singleton pattern is the way to go, but it is hard to judge if it would really improve your code without knowing how you are actually programming.
This shows an implementation of your class as singleton:
class DatabaseConnection {
protected static $instance = null;
private $link;
public $filter;
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self;
}
return self::$instance;
}
protected function __construct() {
global $connection;
mb_internal_encoding( 'UTF-8' );
mb_regex_encoding( 'UTF-8' );
$this->link = new mysqli( MY_HOST, MY_USER, MY_PASS, MY_DB );
$this->link->set_charset( "utf8" );
if( $this->link->connect_errno )
{
$this->log_db_errors( "Connect failed", $this->link->connect_error );
echo 'Server error. Please try again sometime. DB';
exit();
}
}
protected function __clone() {
}
// add your other methods
}
You can call the connection by using
$databasecon = DatabaseConnection::getInstance();
By implementing it this way, when you call getInstance it checks if the connection has already been initialised so you can reuse it.
You set the __construct() as protected so the class can not be called without using the getInstance() method, same for __clone().

Related

SQLite Prepared Statements not Inserting

I'm trying to insert into a database using PDO but after finishing the script and testing it out and I am not seeing any sort of input from inserting into the database, I've tried returning errors from PDO but nothing. I'm not sure what's happening
I've updated the parameter names and they do not seem to change anything with the result of the code. Seems the q() function is just having issues.
Database is initialized and looks like:
function __construct() {
if ( ! file_exists( dbpath . DB ) ) {
$this->db = true;
$this->open( dbpath . DB, SQLITE3_OPEN_CREATE|SQLITE3_OPEN_READWRITE ) or $this->db = false;
if ( $this->db == false ) {
return false;
}
$table = "CREATE TABLE link_hits( id INTEGER PRIMARY KEY AUTOINCREMENT, link TEXT NOT NULL, hits INT NOT NULL, date_added datetime default current_timestamp)";
$this->exec($table);
} else {
$this->db = true;
$this->open( dbpath . DB, SQLITE3_OPEN_CREATE|SQLITE3_OPEN_READWRITE ) or $this->db = false;
if ( $this->db == false ) {
return false;
}
}
}
Prepared statement function
function q ( $q, $v ) {
if ( $this->db ) {
$this->securedb = $this->prepare( $q );
foreach ( $v as $k=>$vv ) {
if ( is_numeric( $vv ) ) {
$this->securedb->bindValue($k, $vv, SQLITE3_INTEGER);
} else {
$this->securedb->bindValue($k, $vv, SQLITE3_TEXT);
}
}
$this->errorInfo = $this->errorInfo();
return ( ( $this->handle = $this->execute() ) == true ) ? $this->handle : false;
}
return false;
}
Add link function
function addlink ( $link ) {
if ( $this->linkexists( $link ) ) {
return false;
}
$this->que = "INSERT INTO link_hits (link, hits) VALUES (:link, :hits)";
$this->input = array(
':link' => $link,
':hits' => 0
);
return ( $this->q( $this->que, $this->input ) ) ? true : false;
}
Am I not forming my statement correctly? I followed several tutorials. I'm really used to MySQL but will not have access to it where this will be. :(
Even my linkexists function throws a false. And yes, the link is there, I forced it in with a normal query.
function linkexists( $link ) {
$this->que = "SELECT link FROM link_hits WHERE type='table' AND link=':link'";
$this->input = array(
':link' => $link
);
return ( ( $this->handle = $this->q( $this->que, $this->input ) ) == true ) ? true : false;
}
Parameter names must not end with a semicolon:
$this->que = "INSERT ... VALUES (:link, :hits)";

PHP error fetching json file

Can someone help why my JSON file can't show? I beginner for JSON. This is my code, its only show blank document. I am learning this tutorial from this website http://contohprogramandroid.blogspot.com/2013/10/contoh-program-android-aplikasi-wisata.html. thank you so much.
this my image when running the code.
//this is the code webservice.php
<?php
class Database {
private $host = "localhost";
private $user = "root";
private $pass = "";
private $db = "wisata_jogja";
private $conn;
// constructor
function __construct() {
try{
$this->conn = new PDO( "mysql:host=".$this->host.";dbname=".$this->db, $this->user, $this->pass );
}catch( PDOException $e ) {
echo "error pdo $e";
}
}
public function showAllData( $table ) {
$sql ="SELECT * FROM $table";
$q = $this->conn->query( $sql ) or die( "Failed !!" );
while ( $r = $q->fetch( PDO::FETCH_ASSOC ) ) {
$data[] = $r;
}
return $data;
}
}
$database = new Database();
$response = array();
if ( isset( $_GET['get'] ) && $_GET['get']=='lokasi' ) {
$response['location'] = array();
foreach ( $database->showAllData( 'lokasi' ) as $value ) {
$kode = array();
extract( $value );
$kode['id'] = $id;
$kode['nama'] = $nama;
$kode['alamat'] = $alamat;
$kode['gambar'] = $gambar;
$kode['lat'] = $lat;
$kode['lng'] = $lng;
array_push( $response['location'], $kode );
}
echo json_encode( $response );
}
?>
Your condition to output is this:
if ( isset( $_GET['get'] ) && $_GET['get']=='lokasi' ) {
Thus, the script won't output any JSON since condition is not met.
From your screenshot it is clear your are missing the GET parameters.
In your browser add the parameter to the url:
http://localhost/wisata/webservice.php?get=lokasi
It's always good to take alternative action when condition is not true.
You should always echo something just so you know what is going on:
if ( isset( $_GET['get'] ) && $_GET['get']=='lokasi' ) {
//..............
echo json_encode( $response );
}else{
echo "cannot output JSON data: parameter is missing!!;
}
Are you sure that you pass the GET variable "lokasi" to your script ?
Otherwise, it would not go through the if condition
if(isset($_GET['get'] ) && $_GET['get']=='lokasi')
You can check this by trying to dump the variable or any foobar data inside the if condition to verify your code goes that far, for instance :
if(isset($_GET['get'] ) && $_GET['get']=='lokasi') {
$response['location'] = array();
$myTest = array('test');
var_dump($myTest); // Should display something on screen
// The rest of your code here

getting lastInsertId from PDO class

I'm using this class to connect to database. It works just fine, except I couldn't get the lastInsertId().
<?php
class connDB
{
public function connDB()
{
require_once( 'dbconfig/config.php' );
$this->confPDO = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT => false,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES UTF8"
);
try
{
$this->dbc = new PDO( "mysql:host=$this->dbHost;dbname=$this->dbName",
$this->dbUser, $this->dbPass, $this->confPDO );
}
catch( PDOException $errMsg )
{
return false;
}
}
public function exec( $sql, array $params = array() )
{
try
{
$this->stmt = $this->dbc->prepare( $sql );
if ( count( $params ) > 0 )
{
foreach ( $params as $k=>$v )
{
$this->bind($k, $v);
}
}
return $this->stmt->execute();
}
catch( PDOException $errMsg )
{
$this->dbc = null;
return false;
}
}
public function bind( $param, $value, $type = null )
{
if ( is_null( $type ) )
{
switch ( true )
{
// Boolen parameter
case is_bool( $value ):
$type = PDO::PARAM_BOOL;
break;
// Integer parameter
case is_int( $value ):
$type = PDO::PARAM_INT;
break;
// Null parameter
case is_null( $value ):
$type = PDO::PARAM_NULL;
break;
// String parameter
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue( $param, $value, $type );
}
public function single()
{
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
public function resultset()
{
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function rowCount()
{
return $this->stmt->rowCount();
}
}
Usage: [SELECT]
$sql = "SELECT * FROM < table >";
$db->exec($sql, $params);
$rows = $db->resultset();
foreach ($rows as $row)
{
echo $row['< column >'] . "\n";
}
Usage: [INSERT]
$sql = "INSERT INTO < table > (< column_1 >, < column_2 >, ... ) VALUES
(:valuename_1,
:valuename_2, ...)";
$params = array(':valuename_1' => 'value', ':valuename_2' => 'value', ...);
$db->exec($sql, $params);
I tried to do it this way:
include_once'classe.php';
$db = new connDB();
$sql = "INSERT INTO < table > (< column_1 >, < column_2 >, ... ) VALUES
(:valuename_1,
:valuename_2, ...)";
$params = array(':valuename_1' => 'value', ':valuename_2' => 'value', ...);
$db->exec($sql, $params);
$id = $db->lastInsertId();
I am getting an error:
Fatal error: Call to undefined method connDB::lastInsertId() in
I've tried adding a method into the class:
public function lastinsert()
{
// Return result
return $this->stmt->lastInsertId();
}
Then I called it like this this:
$db = new connDB();
$id = $db->lastinsert();
The error this time was
Fatal error: Call to undefined method PDOStatement::lastInsertId() in
There is no lastInsertId() method in your class.
You need to add it to the connDB class.
you need to call $dbc, not $stmt to get lastInsertId();
$this->dbc->lastInsertId();
as this function belongs to PDO class, not PDO statement class
Also, this piece of code may cause the problem
catch( PDOException $errMsg )
{
$this->dbc = null;
return false;
}
}
Make your exec() function this way
public function exec( $sql, array $params = array() )
{
$this->stmt = $this->dbc->prepare( $sql );
foreach ( $params as $k=>$v )
{
$this->bind($k, $v);
}
return $this->stmt->execute();
}
Using the same database class and was able to use lastInsertId like this:
$db = new connDB();
...
$_SESSION['users_id'] = $db->dbc->lastInsertId('id');
If you are using the model's save function:
$row->save();
You can use:
return $row->save();
which returns the id

Fatal error: Call to a member function fetch() on a non-object in

i wrote this below code for my groups in my site..
public function set_group_id($group_id)
{
$db2 = & $this->network->db2;
/* if( $this->id ) {
return FALSE;
} */
if( ! $group_id ) {
return FALSE;
}
if( ! $g = $this->network->get_group_by_id($group_id) ) {
return FALSE;
}
if( !$g->is_public && $this->user->id>0 && !$this->user->is_network_admin ) {
$users = $this->network->get_group_invited_members($g->id);
if( !$users || !in_array(intval($this->user->id),$users) ) {
return FALSE;
}
}
$D->i_am_network_admin = ( $this->user->is_logged && $this->user->info->is_network_admin > 0 );
$D->i_am_admin = $D->i_am_network_admin;
if( !$D->i_am_network_admin ) {
$D->i_am_admin = $db->fetch('SELECT id FROM groups_admins WHERE group_id="'.$g->id.'" AND user_id="'.$this->user->id.'" LIMIT 1') ? TRUE : FALSE;
}
if( $g->mojaz && !$this->user->i_am_admin ) {
return FALSE;
}
$this->group = $g;
$this->to_user = FALSE;
return TRUE;
}
my error in this line ...
$D->i_am_admin = $db->fetch('SELECT id FROM groups_admins WHERE group_id="'.$g->id.'" AND user_id="'.$this->user->id.'" LIMIT 1') ? TRUE : FALSE;
i want create limiter for website groups if user is admin of site he can send a post
or if user is admin of group can send post else return false.
In your error line $db is null, because $db hadn't been declared in your function set_group_id(). I see only database object $db2
$db2 =& $this->network->db2
Try to replase $db to $db2. If $db2 contains correct database object and a handle to an open connection it will works

PHP OOP Session Object - Won't Persist Without Serialize Un-Serialize

I'm trying to figure out why the code below won't persist my $_SESSION['objSession'] object across pages unless i keep the serialize/unserialize in place below. I get tired of manually serializing/unserializing to make object changes in the session and people keep saying i shouldn't have to do it but i do see other complaints about session objects not persisting without it on the web including here on stack... PHP 5.3 Apache 2.2 Windows 2008.
<?php require_once("/php/php_clsSession.php");?>
<?php session_start(); ?>
<?php
// Session Object Create/Log
$objSession = new clsSession;
if ( !(isset($_SESSION['objSession']) )) {
// This line will populate some properties in the obj
// like Session_ID and Create_dt
$objSession->CreateSession(session_id(),$_SERVER);
}
else {
// this code will only run if the session is already
// set
$objSession = unserialize($_SESSION['objSession']);
$objSession->UpdateSession(session_id(),$_SERVER);
}
// Update Session Object
$_SESSION['objSession'] = serialize($objSession);
unset($objSession);
?>
---- clsSession Below this line... you can ignore the db include as the code has the same problem without using the db functionality and i have the db function temporarily commented anyhow....
<?php
// -----------------------------------------------------------------
// Program Type: Class
// Program Name: clsSession
// Program Date: 01/08/2012 Programmer: Tim Wiley
// Description: Standard class for session creation/update
// -----------------------------------------------------------------
class clsSession {
// Properties
public $Session_Id = null;
public $Creation_Dt = null;
public $Action_Dt = null;
public $Session_IP_Address = null;
public $Browser_Type = null;
public $Display_Resolution = null;
public $Is_Https_Ind = null;
public $Is_Logged_In_Ind = 0;
public $User_Key = null;
public $User_Id = null;
public $Email_Address = null;
public $Request_Method = null;
public $Page_Requested = null;
public $Page_Request_Params = null;
public $Page_Action = null;
public $Login_Attempts = 0;
public $Max_Login_Attempts = 3;
private function UpdateSessionClassData (&$xSessionId = null, &$xSessionObj = null, &$xPageAction = "N/A" ) {
$this->Session_Id = &$xSessionId;
$this->Action_Dt = date( 'Y-m-d H:i:s', time( ));
$this->Session_IP_Address = substr(trim(&$xSessionObj['REMOTE_ADDR']),0,24);
$this->Browser_Type = substr(trim(&$xSessionObj['HTTP_USER_AGENT']),0,140);
$this->Request_Method = substr(trim(&$xSessionObj['REQUEST_METHOD']),0,24);
$this->Page_Requested = substr(trim(&$xSessionObj['SCRIPT_NAME']),0,140);
$this->Page_Request_Params = substr(trim(&$xSessionObj['QUERY_STRING']),0,140);
$this->Is_Https_Ind = &$xSessionObj['SERVER_PORT'] == 443 ? 1 : 0;
if (is_null($this->Display_Resolution)) {
require_once('/javascript/js_SaveScreenResolutionInCookie.js');
$this->Display_Resolution = !( IS_NULL( $_COOKIE['users_resolution'] )) ? substr(trim($_COOKIE['users_resolution']),0,16) : "N/A";
}
$this->Page_Action = substr(trim(&$xPageAction),0,32);
}
// Initialize Session objSession for $_SESSION
public function CreateSession($xSessionId = null, &$xSessionObj = null ) {
$this->Creation_Dt = date( 'Y-m-d H:i:s', time( ));
$this->UpdateSessionClassData(&$xSessionId, &$xSessionObj);
// $this->WriteSessionToDb();
}
// Update Session objSession for $_SESSION
public function UpdateSession($xSessionId = null, &$xSessionObj = null, $xPageAction = "N/A" ) {
$this->UpdateSessionClassData(&$xSessionId, &$xSessionObj, &$xPageAction);
// $this->WriteSessionActivityToDb();
}
// Writes the session data to database
public function WriteSessionToDb($xUserType = "Web") {
$objConnect = new clsDb;
$objDb = $objConnect->GetDbConnection($xUserType);
//$objDb = $this->GetDbConnection($xUserType);
$_InsertSQL = new PDOStatement;
$_InsertSQL = $objDb->prepare("INSERT INTO T_SESSION_STATS(" .
"F_ACTION_DT, F_SESSION_ID, F_SESSION_IP_ADDRESS, F_BROWSER_TYPE," .
"F_DISPLAY_RESOLUTION, F_PAGE_REQUESTED, F_PAGE_REQUEST_PARAMS," .
"F_REQUEST_METHOD, F_IS_HTTPS_IND, F_IS_LOGGED_IN_IND, F_USER_KEY)" .
"Values (?,?,?,?,?,?,?,?,?,?,?)");
$_InsertSQL->bindParam(1, $this->Action_Dt );
$_InsertSQL->bindParam(2, $this->Session_Id );
$_InsertSQL->bindParam(3, $this->Session_IP_Address );
$_InsertSQL->bindParam(4, $this->Browser_Type );
$_InsertSQL->bindParam(5, $this->Display_Resolution );
$_InsertSQL->bindParam(6, $this->Page_Requested );
$_InsertSQL->bindParam(7, $this->Page_Request_Params );
$_InsertSQL->bindParam(8, $this->Request_Method );
$_InsertSQL->bindParam(9, $this->Is_Https_Ind );
$_InsertSQL->bindParam(10, $this->Is_Logged_In_Ind );
$_InsertSQL->bindParam(11, $this->User_Key );
try {
$objDb->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$objDb->beginTransaction();
$_InsertSQL->execute();
$objDb->commit();
unset($objDb);
} catch (Exception $e) {
$objDb->rollBack();
echo "Failed: " . $e->getMessage();
unset($objDb);
unset($objConnect);
}
}
// Writes the session data to database
public function WriteSessionActivityToDb($xUserType = "Web",$xPageAction = "N/A") {
$objConnect = new clsDb;
$objDb = $objConnect->GetDbConnection($xUserType);
//$objDb = $this->GetDbConnection($xUserType);
$_InsertSQL = new PDOStatement;
$_InsertSQL = $objDb->prepare("INSERT INTO T_SESSION_ACTIVITIES(" .
"F_ACTION_DT, F_SESSION_ID, F_SESSION_IP_ADDRESS, " .
"F_PAGE_REQUESTED, F_PAGE_REQUEST_PARAMS," .
"F_REQUEST_METHOD, F_PAGE_ACTION, F_IS_HTTPS_IND, F_IS_LOGGED_IN_IND, F_USER_KEY)" .
"Values (?,?,?,?,?,?,?,?,?,?)");
$_InsertSQL->bindParam(1, $this->Action_Dt );
$_InsertSQL->bindParam(2, $this->Session_Id );
$_InsertSQL->bindParam(3, $this->Session_IP_Address );
$_InsertSQL->bindParam(4, $this->Page_Requested );
$_InsertSQL->bindParam(5, $this->Page_Request_Params );
$_InsertSQL->bindParam(6, $this->Request_Method );
$_InsertSQL->bindParam(7, substr(trim($xPageAction),0,32));
$_InsertSQL->bindParam(8, $this->Is_Https_Ind );
$_InsertSQL->bindParam(9, $this->Is_Logged_In_Ind );
$_InsertSQL->bindParam(10, $this->User_Key );
try {
$objDb->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$objDb->beginTransaction();
$_InsertSQL->execute();
$objDb->commit();
unset($objDb);
unset($objConnect);
} catch (Exception $e) {
$objDb->rollBack();
unset($objDb);
echo "Failed: " . $e->getMessage();
}
}
}
?>
The issue seems to be in your clsSession class. This is using &. Since the session object is serialized these references aren't stored correctly. Try removing these (i.e. change UpdateSessionClassData and UpdateSession to remove the & from parameters) and see if this sorts the issue.
to start, put session_start(); before require_once and add var_dump($_SESSION) for debug.

Categories