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)";
Related
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().
I'm trying to save my data using php. This is how I tried:
<?php
session_start();
if(!isset($_SESSION["MemberID"])) header("Location:logout.php");
include '../config.php';
include '../momdb.php';
$page_title = "Customers";
$mode = "Save";
$db = 'db';
$showmessage = false;
$message = "";
if (isset ( $_POST ["btnSave"] )) {
$data = new table ();
$data->MomID = $_POST ["CustomerID"];
$data->CustomerName = $_POST ["CustomerName"];
$data->FromDate = string_to_date ( $_POST ["FromDate"] );
$data->ToDate = string_to_date ( $_POST ["ToDate"] );
$data->CreatedBy = $_SESSION["MemberID"];
$data->CreatedDatetime = date ( "Y-m-d H:i:s" );
$data->LastModifiedBy = $_SESSION["MemberID"];;
$data->LastModifiedDatetime = date ( "Y-m-d H:i:s" );
$rows = array ();
if (intval ( $data->CustomerID) > 0) {
$rows = $db::Update ( $data );
} else {
$rows = $db::Save ( $data );
}
if (intval ( $rows ["WebID"] ) > 0) {
$date = new DateTime ();
header ( "Location: customerlist.php?msg=yes&msgt=s&t=" . $date->getTimestamp () . "&mtext=Record saved successfully" );
} else {
$showmessage = true;
$message = $rows ["Message"];
}
} elseif (isset ( $_GET ["CustomerID"] )) {
$data = $db::GetByID ( $_GET ["CustomerID"] );
if ($data == false) {
$data = new table ();
$data->CustomerID = 0;
}
}
if ($data->CustomerID == "0")
$mode = "Save";
else
$mode = "Update";
?>
This code is for sending my values to the db page for saving them in the DB. I've used the PDO method. This is the first time I'm saving the record this way. That's why there is lots of confusion. The following code shows the Save() method, which I used to save the values to the DB.
public function Save(table $customer) {
$data = new DB ();
$stmt = $data->connection->prepare ( "CALL proc_CreateCustomer (:CustomerName, :FromDate,:ToDate,:CreatedBy, :CreatedDatetime, :LastModifiedBy, :LastModifiedDatetime)" );
$stmt->bindParam ( ':CustomerName', trim ($customer->CustomerName ));
$stmt->bindParam ( ':FromDate', $customer->FromDate );
$stmt->bindParam ( ':ToDate', $customer->ToDate);
$stmt->bindParam ( ':CreatedBy',$customer->CreatedBy );
$stmt->bindParam ( ':CreatedDatetime', $customer->CreatedDatetime );
$stmt->bindParam ( ':LastModifiedBy',$customer->LastModifiedBy );
$stmt->bindParam ( ':LastModifiedDatetime', $customer->LastModifiedDatetime );
$stmt->execute ();
$record = $stmt->fetch ( PDO::FETCH_OBJ );
if ($record == false) {
return array (
"WebID" => 0,
"Message" => $record->Message,
"AppID" => $customer->AndroidID
);
} else {
return array (
"WebID" => $record->CustomerID,
"Message" => $record->Message,
"AppID" => $customer->AndroidID
);
}
}
This is how I've tried. But, whenever I try to save the details, it shows: " Trying to get property of non-object in D:\Workspace\Application\momdb.php on line 39", ie it shows error in the line "Message" => $record->Message,"AppID" => $customer->AndroidID. I don't what's wrong with this. Can someone tell me what should I change so that it work fine?
if ($record == false) {
return array (
"WebID" => 0,
"Message" => $record->Message,
"AppID" => $customer->AndroidID
);
}
In this piece of code $record is false(y), so $record->Message doesn't exist.
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
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
I am trying to delete an array of ids and when it gets deleted I want the uploaded pic associated with it also to get deleted using unlink. I am using joomla and mysql for the admin mvc component in joomla.
My code for controller in remove is has follows:
function remove()
{
$arrayIDs = JRequest::getVar ( 'cid', null, 'default', 'array' );
//Reads cid as an array
$model = & $this->getModel ( 'greetings' );
jimport ( 'joomla.filesystem.file' );
if (is_array ( $arrayIDs ) && count ( $arrayIDs ) > 0) {
foreach ( $arrayIDs as $k => $id ) {
$del = $model->deleteGreetings ( $arrayIDs );
if ($del) {
$getdeleted = $model->getUploadpic ( $id );
$deletefile = JPATH_COMPONENT . DS . "uploads" . DS . $uploadedfile;
unlink ( $deletefile );
}
}
}
if ($arrayIDs === null) { //Make sure the cid parameter was in the request
JError::raiseError ( 500, 'cid parameter missing from the request' );
}
$redirectTo = JRoute::_ ( 'index.php?option=' . JRequest::getVar ( 'option' ) );
$this->setRedirect ( $redirectTo, 'Deleted...' );
}
...and for the model my code is:
function deleteGreetings($arrayIDs) {
$query = "DELETE FROM #__greetings WHERE id IN (" . implode ( ',', $arrayIDs ) . ")";
$db = $this->getDBO ();
$db->setQuery ( $query );
if (! $db->query ()) {
$errorMessage = $this->getDBO ()->getErrorMsg ();
JError::raiseError ( 500, 'Error deleting greetings: ' . $errorMessage );
} else {
return TRUE;
}
}
You have a few problems in your code:
$uploadedfile is never declared but it is used to find the file path. I assume this is the same as $getdeleted.
You have a foreach loop around the elements in your array which will pick up each element in turn. However you model function deleteGreetings takes the entire array. Your should remove this function call from your loop else it will be called each for every element in the array. You only want to call this once.
Only at the end of your controller do you check if your cid param is null ... what is the point? You should check this first before trying to run any of the other code.
I would do something like this:
$arrayIDs = JRequest::getVar ( 'cid', null, 'default', 'array' );
if ($arrayIDs === null) { //Make sure the cid parameter was in the request
JError::raiseError ( 500, 'cid parameter missing from the request' );
}
$model = & $this->getModel ( 'greetings' );
jimport ( 'joomla.filesystem.file' );
if (is_array ( $arrayIDs ) && count ( $arrayIDs ) > 0) {
$del = $model->deleteGreetings ( $arrayIDs );
// check this outside the loop, if it is inside you are checking it for
// each element in the array. Here we check once and then go forward.
if ($del) {
foreach ( $arrayIDs as $k => $id ) {
$uploadedfile = $model->getUploadpic ( $id );
$deletefile = JPATH_COMPONENT . DS . "uploads" . DS . $uploadedfile;
JFile::delete($deletefile);
//unlink ( $deletefile );
}
}
}