I'm trying to use PDO (php data object) to execute queries in a .php file like so:
global $db, $table;
$sth = $db->prepare('INSERT INTO $table(user, timerun, magexp, crimsons, blues, golds, greens) VALUES (:user,:timerun,:magexp,:crimsons,:blues,:golds,:greens) ON DUPLICATE KEY UPDATE timerun=timerun+:timerun, magexp=magexp+:magexp, crimsons=crimsons+:crimsons, blues=blues+:blues, golds=golds+:golds, greens=greens+green');
$sth->execute(array(':user' => $user, ':timerun' => $timerun, ':magexp' => $magexp, ':crimsons' => $cr, ':blues' => $bl, ':golds' => $go, ':greens' => $gr));
echo "success";
However, it doesn't actually update my table. I don't get an error or anything.
Am I doing something wrong or is PDO not supported? The PDO docs said "Beware: Some MySQL table types (storage engines) do not support transactions. When writing transactional database code using a table type that does not support transactions, MySQL will pretend that a transaction was initiated successfully. In addition, any DDL queries issued will implicitly commit any pending transactions."
I'm fairly certain my MySQL tables do support transactions, because the regular 'mysql_query' does work.
Thanks.
I'm not sure about Your code, You have variable inside single quoted string it will not work, You should use double quotation like this:
global $db, $table;
$sth = $db->prepare("INSERT INTO $table(user, timerun, magexp, crimsons, blues, golds, greens) VALUES (:user,:timerun,:magexp,:crimsons,:blues,:golds,:greens) ON DUPLICATE KEY UPDATE timerun=timerun+:timerun, magexp=magexp+:magexp, crimsons=crimsons+:crimsons, blues=blues+:blues, golds=golds+:golds, greens=greens+green:");
$sth->execute(array(':user' => $user, ':timerun' => $timerun, ':magexp' => $magexp, ':crimsons' => $cr, ':blues' => $bl, ':golds' => $go, ':greens' => $gr)); echo "success";
For security:
First of all i would create some associative array with all possible tables from project as keys and then check if table from variable exists as array index using if(isset($validTables[$table])) and then continue the query. For example
<?php
$validTables = array('foo' => true, 'bar' => true, 'other' => true);
if(isset($validTables[$table]))
{
// query logic here
}
else throw new Exception(sprintf('Security error %s table not exists', $table));
Check this code because i wrote it without parsing with php
Related
I'm trying to insert an array of data into a table in database but an error said Array to string conversion error
This is the post function in my controller, first i post an array of data. The values of the array will be the names, and numbers, they are not id. The id is only kodejdwl. This will be pass to my model
function index_post() {
$data = array(
'kodejdwl' => $this->post('kodejdwl'),
'tahun_akad' => $this->post('kode_tahun_akad'),
'semester' => $this->post('semester'),
'mk' => $this->post('mk'),
'ruangan' => $this->post('ruangan'),
'nama_dosen' => $this->post('nama_dosen'),
'namakelas' => $this->post('nama_kelas'),
'jam_mulai' => $this->post('jam_mulai'),
'jam_selesai' => $this->post('jam_selesai'),
);
}
After the data from above code is passed to the model. I created some new variables which are the id of each the name of the value in the array data. e.g if the value of data['mk'] is Website then the id will be 1 and that id will be stored in variable $kodemk and i do it to each value in the data. Then i created new_data which stores array of the id's which i previously made. Then i insert that array into one table in my database. I thought it would be fine but it said Array to string conversion error. What should i do so i could insert that array into the table in my database?
public function insert($data){
$this->db->select('thn_akad_id');
$tahunakad_id = $this->db->get_where('tik.thn_akad',array('tahun_akad'=>$data['tahun_akad'],'semester_semester_nm'=>$data['semester']))->result();
$this->db->flush_cache();
$this->db->select('kodemk');
$kode_mk = $this->db->get_where('tik.matakuliah',array('namamk'=>$data['mk']))->result();
$this->db->flush_cache();
$ruangan = $this->db->get_where('tik.ruangan', array('namaruang' => $data['ruangan']), 1)->result();
$this->db->flush_cache();
$this->db->select('nip');
$nip_dosen = $this->db->get_where('tik.staff',array('nama'=>$data['nama_dosen']))->result();
$this->db->flush_cache();
$this->db->select('kodeklas');
$kodeklas = $this->db->get_where('tik.kelas',array('namaklas'=>$data['namakelas']))->result();
$this->db->flush_cache();
$this->db->select('kode_jam');
$kode_mk = $this->db->get_where('tik.wkt_kuliah',array('jam_mulai'=>$data['jam_mulai'],'jam_selesai'=>$data['jam_selesai']))->result();
$this->db->flush_cache();
$new_data = array(
'kodejdwl' => $data['kodejdwl'],
'thn_akad_thn_akad_id' => $tahunakad_id,
'matakuliah_kodemk' => $kode_mk,
'ruangan_namaruang' => $ruangan,
'staff_nip' => $nip_dosen,
'kelas_kodeklas' => $kodeklas,
);
$insert = $this->db->insert('tik.jadwal_kul', $new_data);
return $this->db->affected_rows();
}
You probably want to use row() instead of result() because it'll contain only one result that you want. If you want to use result() and store multiple values then you'll have to use implode to concatenate them and store it as a string.
I've written a possible solution for your problem; Some things were missing, so I've mentioned them in the comments. See if this helps you.
public function insert($data){
$this->db->select('thn_akad_id');
$tahunakad_id = $this->db->get_where('tik.thn_akad',array('tahun_akad'=>$data['tahun_akad'],'semester_semester_nm'=>$data['semester']))->row(); // use row here
$this->db->flush_cache();
$this->db->select('kodemk');
$kode_mk = $this->db->get_where('tik.matakuliah',array('namamk'=>$data['mk']))->row();
$this->db->flush_cache();
// remove your_ruangan_column with your desired column name
$this->db->select('your_ruangan_column');
$ruangan = $this->db->get_where('tik.ruangan', array('namaruang' => $data['ruangan']), 1)->row();
$this->db->flush_cache();
$this->db->select('nip');
$nip_dosen = $this->db->get_where('tik.staff',array('nama'=>$data['nama_dosen']))->row();
$this->db->flush_cache();
$this->db->select('kodeklas');
$kodeklas = $this->db->get_where('tik.kelas',array('namaklas'=>$data['namakelas']))->row();
$this->db->flush_cache();
// Not sure where this ↓↓ is being used but you can use it the same way as others
$this->db->select('kode_jam');
// duplicate variable name here ↓↓ (fix this)
$kode_mk = $this->db->get_where('tik.wkt_kuliah',array('jam_mulai'=>$data['jam_mulai'],'jam_selesai'=>$data['jam_selesai']))->row();
$this->db->flush_cache();
$new_data = array(
'kodejdwl' => $data['kodejdwl'],
'thn_akad_thn_akad_id' => $tahunakad_id->thn_akad_id, // {$tahunakad_id} consists an object with the key {thn_akad_id}-- table_column_name
'matakuliah_kodemk' => $kode_mk->kodemk, // ...
'ruangan_namaruang' => $ruangan->your_ruangan_column, // ...
'staff_nip' => $nip_dosen->nip, // ...
'kelas_kodeklas' => $kodeklas->kodeklas // ...
);
$insert = $this->db->insert('tik.jadwal_kul', $new_data);
return $this->db->affected_rows();
}
Your are making a total of 7 separate trips to the database. Best practice recommends that you always minimize your trips to the database for best performance. The truth is that your task can be performed in a single trip to the database so long as you set up the correct INSERT query with SELECT subqueries.
I don't know what your non-English words are, so I will use generalized terms in my demo (I've tested this successfully in my own CI project). I am also going to reduce the total subqueries to 3 to reduce the redundance in my snippet.
$value1 = $this->db->select('columnA')->where('cond1', $val1)->get_compiled_select('childTableA');
$value2 = $this->db->select('columnB')->where('cond2', $val2)->get_compiled_select('childTableB');
$value3 = $this->db->select('columnC')->where('cond3', $val3)->get_compiled_select('childTableC');
return (int)$this->$db->query(
"INSERT INTO parentTable
(column1, column2, column1)
VALUES (
($value1),
($value2),
($value3)
)"
);
// to mirror your affected rows return... 1 will be returned on successful insert, or 0 on failure
Granted this isn't using the ActiveRecord technique to form the complete INSERT query, but this is because CI doesn't allow subqueries in the VALUES portion (say, if you were to use the set() method). I am guessing this is because different databases use differing syntax to form these kinds of INSERTs -- I don't know.
The bottom line is, so long as you are fetching a single column value from a single row on each of these sub-SELECTs, this single query will run faster and with far less code bloat than running N number of individual queries. Because all of the variables involved are injected into the sql string using get_compiled_select() the stability/security integrity should be the same.
I have this upsert query written in postgreSQL
$statement = 'INSERT INTO "CharactersUnlockToBuyLevels"
("CharacterId", "LevelId", "AmountToBuy", "EagleStatueId", "Location",
"MapCoordinateTop", "MapCoordinateLeft")
VALUES
(:CharacterId, :LevelId, :AmountToBuy, :EagleStatueId, :Location,
:MapCoordinateTop, :MapCoordinateLeft)
ON CONFLICT
("CharacterId")
DO UPDATE
SET
"LevelId" = EXCLUDED."LevelId",
"AmountToBuy" = EXCLUDED."AmountToBuy",
"EagleStatueId" = EXCLUDED."EagleStatueId",
"Location" = EXCLUDED."Location",
"MapCoordinateTop" = EXCLUDED."MapCoordinateTop",
"MapCoordinateLeft" = EXCLUDED."MapCoordinateLeft"
RETURNING "CharacterUnlockToBuyLevelId"
';
The query works fine, and if I run it in PgAdmin, I get the "CharacterUnlockToBuyLevelId" back as expected. However if I prepare it and execute it using PHP's PDO then I can't seem to get the RETURNING value back.
$stmt = $this->db->prepare($statement);
$returnedId = $stmt->execute(array(
'CharacterId' => $characterId,
'LevelId' => $unlockMethod['LevelId'],
'AmountToBuy' => $unlockMethod['AmountToBuy'],
'EagleStatueId' => $unlockMethod['EagleStatueId'],
'Location' => $unlockMethod['Location'],
'MapCoordinateTop' => $unlockMethod['MapCoordinateTop'],
'MapCoordinateLeft' => $unlockMethod['MapCoordinateLeft'],
));
This just returns true, so $returnedId will not actually hold the id but just the value true. How can I get the RETURNING value from the upsert query back with PDO's prepared statements?
from http://php.net/manual/en/pdostatement.execute.php:
public bool PDOStatement::execute ([ array $input_parameters ] )
to get returned val, try fetchAll
$stmt = $this->db->prepare($statement);
$returnedId = $stmt->execute(array(
'CharacterId' => $characterId,
'LevelId' => $unlockMethod['LevelId'],
'AmountToBuy' => $unlockMethod['AmountToBuy'],
'EagleStatueId' => $unlockMethod['EagleStatueId'],
'Location' => $unlockMethod['Location'],
'MapCoordinateTop' => $unlockMethod['MapCoordinateTop'],
'MapCoordinateLeft' => $unlockMethod['MapCoordinateLeft'],
));
$yourVal=$stmt->fetchAll();
If you’re prepared to extend the PDOStatement class, you can simplify the process a little. The trick is to wrap the fetchAll inside your extended version of the execute method.
Because the PDOStatement is generated indirectly, you first need to tell PDO to use your extended version, rather than the standard version:
$pdo=new PDO($dsn,$user,$password) or die('oops');
$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DBStatement',array($pdo)));
… where DBStatement will be your extended PDOStatement.
You can then extend the class as follows:
class DBStatement extends PDOStatement {
public $pdo;
protected function __construct($pdo) {
$this->pdo = $pdo;
}
function executeReturning($data=null) {
parent::execute($data);
return $this->fetchAll();
}
}
The first part is required to get your new class to start off the same as the original. The second part executes the statement, and then returns the result.
You can then call it as follows:
$sql='INSERT INTO testing(data) VALUES(?) RETURNING id,data';
$pds=$pdo->prepare($sql);
print_r($pds->executeReturning(['this space for rent']));
There is a problem in inserting to MongoDB database. It is not insert to database in right order.
We read the writing concern in MongoDB:
http://www.php.net/manual/en/mongo.writeconcerns.php
We use mongoDB 2.6 and PHP driver 1.6 with following sample code:
set_message_sample('1');
set_message_sample('2');
set_message_sample($id) {
$connecting_string = sprintf('mongodb://%s:%d/%s', $hosts, $port,$database), // fill with right connection setting
$connection= new Mongo($connecting_string,array('username'=>$username,'password'=>$password)); // fill with proper authentication setting
$dbname = $connection->selectDB('dbname');
$collection = $dbname->selectCollection('collection');
$post = array(
'title' => $id,
'content' => 'test ' . $id,
);
$posts->insert($insert,array("w" => "1"));
Sometimes the result is inserting "2" before "1" to database. We want to inserting in right order (first "1" and next "2") all the times. I also notice that we order the collection with mongoID which automatically set by mongoDB.
We check many options but the problem not solved. How we could solve it? ( How we could disable something like cache or isolate the insert queue to MongoDB.)
So, i think you could insert the second only after the confirmation of the first one. since the insert is asynchronous, you can't be sure who goes first. So you must insert only after the confirmation of the first one.
I am very new to stored procedures and the PDO library so please take it easy on me. I am trying to execute a stored procedure using a PDO function and retrieve the recordsets along with the output parameters. Which function should I use and what parameters are necessary?
If I want to execute basic statements using the function like the following example, what PDO method should I use? e.g.
$mssql = new mssql;
$mssql->sql('stored_procedure()');
$mssql->sql('SELECT * FROM [test]');
I want the function to return the correct results dependant on the statement type. Is this going to be possible?
UPDATE
Just in case I didnt make it very clear, the 'mssql' class uses the PDO class to execute queries. At the moment I am using:
$PDO->prepare();
$PDO->exec();
After researching around the internet, I found it is in fact very simple using the PDO prepare, bindParam and execute methods.
An example of a store procedure using my class:
$mssql->bind_params = array(
'BatchNum' => array(
'value' => 'SS000008'
),
'RecCount' => array(
'value' => 0,
'type' => PDO::PARAM_INT,
'length' => 8
)
);
$mssql->sql("{CALL sp_Batch_Sales(#paramOne=:paramOne,#paramTwo=:paramTwo)}");
This is converted to:
$query = $PDO->prepare({CALL sp_Batch_Sales(#paramOne=:paramOne,#paramTwo=:paramTwo)});
$query->bindParam(':paramOne',$returned_parameters['paramOne']);
$query->bindParam(':paramTwo',$returned_parameters['paramTwo'],PDO::PARAM_INT,8);
$query->execute();
The recordsets can then be retrieved using:
do{
// Get the results
$results = $query->fetchAll(PDO::FETCH_ASSOC);
// Only place the results into the array if they exist
if(!empty($results)){
$data[$i]['results'] = $results;
}
// Set the number of rows in the result array
$data[$i]['rows'] = $query->rowCount();
// Increment i
$i++;
}while($query->nextRowset());
And the input and output parameters can be retrieved using the array:
$returned_parameters
I hope this helps
I use MongoDB together with PHP. To create a unique document for each user, I set the username to unique with
$db->ensureIndex(array("username" => 1), array("unique" => 1, "dropDups" => 1));
However, if there is a duplicate, the _id value that is being returned for the user is that of the record which got never created and not that of the record which already exists in the db.
Here's the entire function:
function register_user($username, $password, $first_name, $last_name, $email)
{
$m = new Mongo();
$db = $m->users->details;
$db->ensureIndex(array("username" => 1), array("unique" => 1, "dropDups" => 1));
$user_doc = array( "username" => $username, "password" => $password, "first_name" => $first_name, "last_name" => $last_name, "email" => $email);
$db->insert($user_doc);
return $user_doc["_id"]; // here i return the _id
}
How would I go about creating a user database, that has no duplicate usernames?
EDIT:
Here's my temporary solution. I put it right where the insert used to be.
try
{
$db->insert($user_doc,array('safe'=>1));
}
catch ( MongoCursorException $e )
{
// if this did not work, we already have that user inside and want to get his _id
$user = $db->findOne(array('username' => $username, 'password' => $password));
return $user["_id"];
}
If I try to insert it with the safe option, it would always die. Using the try-catch procedure, I try to insert and if it does not work, manually find the _id by username. I'm still not satisfied with this solution, so it would be great if more proficient MongoDB users could give some advice.
First off, you always need that try...catch. The reason you were getting the wrong _id for $user_doc is simply that the driver creates it before sending it to the database. So even if the insert fails it's still on the document.
How would I go about creating a user database, that has no duplicate usernames?
I would start by over-writing the _id field with the user name. The _id is auto-generated as a convenience, but you can set it yourself before you insert.
You will still need to use the try...catch but you will get a specific duplicate key error. You can then use this to correctly handle the case of "that user name already exists".
Here's how I manage to insert if not exists.
$db->update(
array('email' => $email),
array('$setOnInsert' => array('email' => $email)),
array('upsert' => true)
);
This basically just updates when the record exists ("updating" to what it's already set to and $setOnInsert does nothing), but if it doesn't exist, mongo upserts a new record then creates the new key and assigns the value.