Insert Oracle CLOB in CodeIgniter - php

How do we use the CodeIgniter Framework to insert into a table that has a CLOB column?
Table is :
CREATE TABLE NOTIFICATIONS
{
ID NUMBER,
CONTENT CLOB
}
The PHP Code is :
$id = 1;
$content = /* An Incredibly Long & Complex String */
$query = "INSERT INTO notifications (id,content) values (?,?)";
$this->dbconnxn->query($query, array($id,$content));
But this doesn't seem to work.
Any ideas?

CodeIgniter doesn't support this, you need to do it manually. In order to not re-create a connection to the database, you can use the connection ID created by CI:
$this->db->conn_id

I have solved it creating in the model 2 functions 1) for insert and update the clob and 2) for read the clob:
1) In the model the function that I have created to set my Clob is updateClobImg64, it is called after the insert :
public function create_file($file){
$file->file_pk1=$this->getMaxPk1();
$data = array(
"file_pk1" => $file->file_pk1,
"file_name" => $file->file_name,
"file_type"=>$file->file_type,
"file_location"=>$file->file_location,
//"file_img64"=>$file->file_img64,
"file_created_date"=>$file->file_created_date,
"file_created_by" => $file->file_created_by,
"file_storage_type"=>$file->file_storage_type,
);
$this->db->insert("file_repository", $data);
if(isset($file->file_img64) && !empty($file->file_img64)) $this->updateClobImg64($file->file_pk1,$file->file_img64);
return $file->file_pk1;
}
public function updateClobImg64($file_pk1,$img64){
$sql='update "file_repository" set "file_img64"=EMPTY_CLOB() where "file_pk1"='.$file_pk1.' RETURNING "file_img64" INTO :clob';
$stid = oci_parse($this->db->conn_id, $sql);
$clob = oci_new_descriptor($this->db->conn_id, OCI_D_LOB);
oci_bind_by_name($stid, ":clob", $clob, -1, OCI_B_CLOB);
oci_execute($stid, OCI_NO_AUTO_COMMIT); // use OCI_DEFAULT for PHP <= 5.3.1
$clob->save($img64);
oci_commit($this->db->conn_id);
$clob->free();
OCIFreeStatement($stid);
}</span>
2) To read the clob is is need a function read that I have implemented this way:
function read_clob($field) {
return $field->read($field->size());
}
and Is called in the model select funtion:
public function get_all(){
$query = $this->db->get_where("file_repository", array());
if($query->num_rows() > 0){
$files=$query->result();
foreach($files as $key=>$row){
$files[$key]->file_img64=$this->read_clob($row->file_img64);
}
return $files;
}
}</span>
Hope this helps some one with this issue.

Related

Weird auto increment issue

I am making a transaction table with an auto increment field of BIGINT(20).
When a new transaction is added, the insert Id is retrieved and formatted to be more readable:
public function add_transaction($paymethod, $cursus_id)
{
$this->load->model('Config_model');
$btw = $this->Config_model->get('transactions.btw');
$query = " INSERT INTO transacties(userid, paymethod, amount, btw_pc)
VALUES((SELECT userid FROM users WHERE lcase(username)=lcase('{$this->session->userdata('username')}')),
'{$paymethod}',
(SELECT prijs FROM p_cursus_uitvoering WHERE uitvoering_id = {$cursus_id}),
{$btw});";
$this->db->query($query);
$insertId = $this->db->insert_id();
$newCode = date('Ymd') . str_pad($insertId, 8, '0', STR_PAD_LEFT);
$this->db->where('transact_id', $insertId);
$this->db->update('transacties', ['transact_id' => $newCode]);
return $newCode;
}
The result is that the ID get updated from eg: 5 to 2015041800000005.
This is working perfectly, but as you can see, the newCode is returned in the function and used by another function where it's reinserted in another table.
Here is where the problem arises, the ID turns into: 201504192058506757.
Even when I echo the newCode, it still prints 201504192058506757.. even though it is inserted correctly once, but incorrectly the second time!
EDIT:
Here is the code snippet in which the function is called:
public function workshop(){
$this->load->model('Inschrijven_model');
$paymethod = $this->input->post("paymethod");
//eigenlijk uitvoering_id.....
$cursus_id = $this->input->post("cursus_id");
if($paymethod == null || $cursus_id == null){
redirect('cursus');
}
if($this->Inschrijven_model->cursus_has_room($cursus_id)){
if(!$this->Inschrijven_model->cursus_ingeschreven($cursus_id)){
$this->load->model('Cc_payment_model');
$this->load->model('Cursus_model');
$amount = $this->Cursus_model->get_price($cursus_id);
$orderId = $this->Cc_payment_model->add_transaction($paymethod, $cursus_id);
$this->Inschrijven_model->cursus_inschrijven($cursus_id,$orderId);
$function = explode('_',$paymethod);
$this->{$function[0]}($function[1], $amount, $orderId);
}else{
echo "Al ingeschreven";
}
}else{
echo "geen ruimte";
}
}
And here is the code snippet in which the return $newCode is being reinserted:
public function cursus_inschrijven($cursus_id,$transaction_id){
$query = " INSERT INTO p_cursus_in(uitvoering_id, userid, transact_id)
VALUES({$cursus_id},(SELECT userid FROM users WHERE lcase(username)=lcase('{$this->session->userdata('username')}')),{$transaction_id})";
$this->db->query($query);
}
It is reinserted so I can make a connection between someone's registration into a class and their payment for that class.
You have to convert the BIGINT to string before you get it into PHP
Here's how you can convert it with a SQL statement:
https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert
I don't know what framework you're using but you have to do a conversion if you're using BIGINT whose length is not supported by PHP directly. It seems that the framework will read the record after updated to check if the operation's done successfully, and because of the process of reading without the conversion, you got a wrong number.
You can also use PHP GMP module to handle BIGINT:
https://php.net/manual/en/book.gmp.php

how to upgrade designation in php data

i am working with a mlm company's site where i hv to design to upgrade the status of member from one step to higher after adding 5 members every member has to upgrade to upper level.i have some code but i dont know how to call this function
here is my code:-
function CheckAndUpgradeDesignation($username,$des)
{
if($des=='Crown')
return;
$q="SELECT introducer_id FROM members WHERE user_id='$username'";
$rs=mysql_query($q);
$r=mysql_fetch_array($rs);
$id=$r['introducer_id'];
$q="SELECT count(*) as total from members WHERE introducer_id='$id' AND designation='$des'";
$rs1=mysql_query($q);
$r1=mysql_fetch_array($rs1);
$t=$r1['total'];
if($t==5)
{
if($des=="VIP")
$des1="Journey";
else
if($des=="Journey")
$des1="Executive";
else
if($des=="Executive")
$des1="DreamFlight";
else
if($des=="DreamFlight")
$des1="Safari";
else
if($des=="Safari")
$des1="GoldRace";
else
if($des=="GoldRace")
$des1="RoyalRace";
else
if($des=="RoyalRace")
$des1="Aashiyana";
else
if($des=="Aashiyana")
$des1="Crown";
$q="UPDATE members SET designation='$des1' WHERE user_id='$id'";
mysql_query($q);
CheckAndUpgradeDesignation($id,$des1);
}
}
pls check anyone is this code looks right or need some change...............if u hv some question ask me
You would call the function like this: CheckAndUpgradeDesignation('1', 'GoldRace');
Also you might rename the function parameter $username to $userid, because the SQL uses user_id.
Please escape the values inserted into the SQL statment properly to avoid injections.
Maybe refactor the function into 3 functions:
fetchDesignation($user_id) - which returns the designation for a user_id
raiseDesignation($des) - which is the logic part to level up and returns the new level or false
updateDesignation($user_id, $des) - which inserts the new level into the db
This suggestions is a bit more flexible, but it depends on the use case.
It allows testing the logic for raiseDesignation() in a seperate unit-test, without touching the db. Also fetching the designation for a user_id is now seperate.
I could refactor your code separating some important tasks. In the other hand, I recommend you don't try to write large functions with lot of code, because it could be no easy to understand.
<?php
function CheckAndUpgradeDesignation($userId, $designation)
{
if ($designation == 'Crown') {
return;
}
$introducerId = GetIntroducerIdByUserId($userId);
$memberTotal = GetTotalOfMembersByIntroducerIdAndDesignationId($introducerId, $designation);
if ($memberTotal == 5) {
$designationValue = VerifyDesignation($designation);
UpdateDesignation($designationValue, $introducerId);
CheckAndUpgradeDesignation($introducerId, $designationValue);
}
}
function VerifyDesignation($designation)
{
$designationList = array(
'VIP' => 'Journey',
'Journey' => 'Executive',
'Executive' => 'DreamFlight',
'DreamFlight' => 'Safari',
'Safari' => 'GoldRace',
'GoldRace' => 'RoyalRace',
'RoyalRace' => 'Aashiyana',
'Aashiyana' => 'Crown'
);
if (key_exists($designation, $designationList)) {
return $designationList[$designation];
}
return null;
}
function GetIntroducerIdByUserId($id)
{
$query = "SELECT introducer_id FROM members WHERE user_id='$id'";
$result = mysql_query($query);
$response = mysql_fetch_array($result);
return $response['introducer_id'];
}
function GetTotalOfMembersByIntroducerIdAndDesignationId($introducerId, $designation)
{
$query = "SELECT count(*) as total from members WHERE introducer_id='$introducerId' AND designation = '$designation'";
$result = mysql_query($query);
$response = mysql_fetch_array($result);
return $response['total'];
}
function UpdateDesignation($designationValue, $introducerId)
{
$query = "UPDATE members SET designation='$designationValue' WHERE user_id = '$introducerId'";
mysql_query($query);
}
Also check VerifyDesignation function it could be more efficient instead use multiple if statements.
I hope it can help you.

Retrieving more than one row of data using PHP

I'm trying to create a function that runs a query that returns all of the data located in my MySQL database.
My current code only returns the one row of data (there are 7)
function staff_get() {
$this->load->database();
$sql = 'SELECT * from Staff';
$query = $this->db->query($sql);
$data = $query->row();
$this->response($data, 200);
}
I'd imagine it has something to do with the line "$data = $query->row();" however I've tried switching "row" with "array" but this doesn't work. The text is designed to come out as plaintext so that I can manipulate it using a jQuery template.
Thank you for your help in advance.
You need to encase the results in a while loop. Something along the lines of this.
function staff_get() {
$this->load->database();
$sql = 'SELECT * from Staff';
$query = $this->db->query($sql);
while($data = $query->row()) {
$this->response($data, 200);
}
}

What is a good wrapper/framework/libraries for dealing with interface PHP applications to an SQL database?

I have a table
$query=
"CREATE TABLE screenshot ".
"(screenshot_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ".
"source_video_id INT UNSIGNED NOT NULL, ".
"screenshot_file_name VARCHAR(128), ".
"x_res INT, ".
"y_res INT, ".
"time INT UNSIGNED);";
mysql_query($query);
Then I insert things into that table.
I often want to do an SQL query and iterate over the result of the query, but end up doing this.
//select all screenshots from video, by video id
$q0=
"SELECT * FROM screenshot ".
"WHERE source_video_id = '$source_video_id' ".
"AND x_res = 120 ".
"AND y_res = 90 ".
"ORDER BY time ASC;";
$r0 = mysql_query($q0);
$n0_num = mysql_numrows($r0);
//for each result
for($n0=0;$n0<$n0_num;$n0++) {
$source_video_id = mysql_result($r0,$n0,'source_video_id');
$time = mysql_result($r0,$n0,'time');
$screenshot_file_name = mysql_result($r0,$n0,'screenshot_file_name');
//do stuff for each returned result!
}
This is just ugly. To get the SQL query results, I have to write this for every column!
$source_video_id = mysql_result($r0,$n0,'source_video_id');
I have to write an ugly loop, get the results for each row returned and do something for each result. Basically I want something like;
foreach($SQL_command) {
//Do for each result
}
I want the column variables for each row to be already set, so that I do not have to do
$source_video_id = mysql_result($r0,$n0,'source_video_id');
For each and every column I want to access!
I am sick of writing boiler plate code to do this for every single table in my data. Are there any frameworks or libraries that would make this less painful?
These are the very basics of a database abstraction layer. It's not hard to program your own, or you can use a generic library like Doctrine or Propel. Every notable PHP framework includes some form of database abstraction as well, you really just need to start using one.
One can suppose I'm a fan of Kohana, but I really love the thing. Get the Kohana 3 and put there the Sprig ORM (it's a fork from original Sprig ORM, but with additional ‘sugar’ :) instead of native Kohana's one. You'll understand how pretty they are together. You'll can access to your tables like this code shows:
//just the basics, updating existing record
$screenshot = Sprig::factory('Screenshot', $id)->load();
$screenshot->x_res = 240;
$screenshot->y_res = 260;
$screenshot->update();
//creating new one
$screenshot = Sprig::factory('Screenshot');
$screenshot->x_res = 300;
$screenshot->y_res = 250;
$screenshot->create();
Additional link to the discussion of the Sprig fork: http://forum.kohanaframework.org/comments.php?DiscussionID=4368
Hope, it'll help you.
If you have the PDO drivers enabled (as you should) you can use the single DB() method as a function from the phunction PHP framework. It was inspired by the DiBi database abstraction layer. The documentation is still underway, but I've posted a short summary in this answer.
function DB($query)
{
static $db = null;
static $result = array();
if (is_null($db) === true)
{
if (preg_match('~^(?:mysql|pgsql):~', $query) > 0)
{
$db = new PDO(preg_replace('~^(mysql|pgsql):(?:/{2})?([-.\w]+)(?::(\d+))?/(\w+)/?$~', '$1:host=$2;port=$3;dbname=$4', $query), func_get_arg(1), func_get_arg(2));
if (preg_match('~^mysql:~', $query) > 0)
{
self::DB('SET time_zone = ?;', 'GMT');
self::DB('SET NAMES ? COLLATE ?;', 'utf8', 'utf8_unicode_ci');
}
}
else if (preg_match('~^(?:sqlite|firebird):~', $query) > 0)
{
$db = new PDO(preg_replace('~^(sqlite|firebird):(?:/{2})?(.+)$~', '$1:$2', $query));
}
}
else if (is_a($db, 'PDO') === true)
{
if (isset($query) === true)
{
$hash = md5($query);
if (empty($result[$hash]) === true)
{
$result[$hash] = $db->prepare($query);
}
if (is_a($result[$hash], 'PDOStatement') === true)
{
if ($result[$hash]->execute(array_slice(func_get_args(), 1)) === true)
{
if (preg_match('~^(?:INSERT|REPLACE)~i', $query) > 0)
{
return $db->lastInsertId();
}
else if (preg_match('~^(?:UPDATE|DELETE)~i', $query) > 0)
{
return $result[$hash]->rowCount();
}
else if (preg_match('~^(?:SELECT|EXPLAIN)~i', $query) > 0)
{
return $result[$hash]->fetchAll(PDO::FETCH_ASSOC);
}
return true;
}
}
return false;
}
}
return $db;
}
Your example query could be written as:
// connect to the MySQL server, do this on your config file or something
DB('mysql://host:port/database_name/', 'username', 'password');
// run the query!
$results = DB('SELECT * FROM screenshot WHERE source_video_id = ? AND x_res = ? AND y_res = ? ORDER BY time ASC;', $source_video_id, 120, 90);
foreach ($results as $result)
{
print_r($result);
}
The above code uses prepared queries which means that you'll also be safe from SQL injection attacks.
PS: I'm biased here, since I'm the developer of the framework. If you run into any problems let me know.
I use RedBean in all my projects and would recommend it without hesitation. The main reasons being:
Minimum configuration required. I don't have to map the database schema into a YAML or JSON file, simply put in the connection parameters and go.
Elegant and easy to understand usage syntax.
Lots of features such as caching and tree relationships.
Pretty good performance.
And here's an example of using it:
$book = R::dispense('book');
$book->title = 'Gifted Programmers';
$book->author = 'Charles Xavier';
$id = R::store($book);

How does this PHP know which array key/values to use?

Below is part of a PHP database class someone else wrote, I have removed about 80% of it's code, all the un-related code to my question has been removed and just the amount remains that allows me to test this class without actually hitting a real database.
This class has a couple methods that let you set a key and value it then turns it into a mysql UPDATE and INSERT sql query using an array. I am trying to figure out how to use this code 100% so I can use this feature of it for UPDATE and INSERTS in my own application.
Basicly from what I gather you do something like this...
// assign some key/values to insert into DB
$db->assign('name', 'dfgd');
$db->assign('age', 87);
$db->assign('sex', 'female');
$db->assign('user_id', 4556);
// Do the insert
$db->insert('testing2');
Now where I am confused is I can keep on running code like this over and over on the page and it always will use the correct set of key/value array sets. Above you can see I used the assign() method 4 times and then call the insert() method which creates this
INSERT INTO test (name, age, sex, user_id) VALUES (jason davis, 26, male, 5345)
Now if I run another set like this on the same page...
// assign some key/values to insert into DB
$db->assign('name', 'dfgd');
$db->assign('age', 87);
$db->assign('sex', 'female');
$db->assign('user_id', 4556);
// Do the insert
$db->insert('testing2');
It then creates this...
INSERT INTO testing2 (name, age, sex, user_id) VALUES (dfgd, 87, female, 4556)
So how does it not combine the 2 sets of 4, so instead of inserting 8 record on the second insert, it completey replaces the first set of 4 values with the new set. This is great and what I want but I do not understand how it is happening? Also can this be improved anyway?
Below is a full class and my demo code, it can be ran without needing to connect to mysql for this demo, it will print to screen the SQL that it builds.
Also where would the public function reset() in the code below need to be used at, or would it not be needed?
<?php
class DB{
public $fields;
public function assign($field, $value){
$this->fields[$field] = ($value)==""?("'".$value."'"):$value;
}
public function assign_str($field, $value){
$this->fields[$field] = "'".addslashes($value)."'";
}
public function reset(){
$this->fields = array();
}
public function insert($table){
$f = "";
$v = "";
reset($this->fields);
foreach($this->fields as $field=>$value){
$f.= ($f!=""?", ":"").$field;
$v.= ($v!=""?", ":"").$value;
}
$sql = "INSERT INTO ".$table." (".$f.") VALUES (".$v.")";
//print SQL to screen for testing
echo $sql;
//$this->query($sql);
return $this->insert_id();
}
public function update($table, $where){
$f = "";
reset($this->fields);
foreach($this->fields as $field=>$value){
$f.= ($f!=""?", ":"").$field." = ".$value;
}
$sql = "UPDATE ".$table." SET ".$f." ".$where;
echo $sql;
//$this->query($sql);
}
public function query($_query){
$this->query = $_query;
$this->result = #mysql_query($_query, $this->link_id) or die( $_query."<p>".mysql_error($this->link_id) );
return $this->result;
}
public function insert_id(){
return #mysql_insert_id($this->link_id);
}
}
// start new DB object
$db = new DB;
// assign some key/values to insert into DB
$db->assign('name', 'jason davis');
$db->assign('age', 26);
$db->assign('sex', 'male');
$db->assign('user_id', 5345);
// Do the insert
$db->insert('test');
echo '<hr />';
// assign some key/values to insert into DB
$db->assign('name', 'dfgd');
$db->assign('age', 87);
$db->assign('sex', 'female');
$db->assign('user_id', 4556);
// Do the insert
$db->insert('testing2');
echo '<hr />';
// assign some key/values to UPDATE the DB
$db->assign('name', 'jason davis');
$db->assign('age', 26);
$db->assign('sex', 'male');
$db->assign('user_id', 5345);
// DO the DB UPDATE
$db->update('blogs', 'WHERE user_id = 23');
?>
Key in associative arrays are unique; assigning a new value erases the old.
If you still open for another database abstaction library, I want to suggest you to use AdoDB. It's can connect to multiple database, so you code will stay the same if you decide to switch database later. It have build in feature to sanitize data before insert/update.
For your code above, when you use AdoDB, you will write it like this:
$adodb =& ADONewConnection($dsn);
$data['name'] = 'dfgd';
$data['age'] = 87;
$data['sex'] = 'female';
$data['user_id'] = 4556;
// Do the insert
$result = $adodb->AutoExecute($table_name, $data, 'INSERT');
//If update, must have one of the key, such as id column
$result = $adodb->AutoExecute($table_name, $data, 'UPDATE', "id=$id");
You can read the documentation from the site, or inside zip file that you can download. I always use this library in all my project, even I prefer it more that build in CodeIgniter database library.
insert() and update() should (originally) set the $this->fields property back to an empty array upon execution, but you somehow (wrongly) deleted that code?
Update your code to this:
public function insert($table){
$f = "";
$v = "";
foreach($this->fields as $field=>$value){
$f.= ($f!=""?", ":"").$field;
$v.= ($v!=""?", ":"").$value;
}
$sql = "INSERT INTO ".$table." (".$f.") VALUES (".$v.")";
$this->reset();
//print SQL to screen for testing
echo $sql;
//$this->query($sql);
return $this->insert_id();
}
public function update($table, $where){
$f = "";
foreach($this->fields as $field=>$value){
$f.= ($f!=""?", ":"").$field." = ".$value;
}
$sql = "UPDATE ".$table." SET ".$f." ".$where;
$this->reset();
echo $sql;
//$this->query($sql);
}
Ok, we have come to the conclusion that my previous answer was right:
Because you use the name keys, it replaces the old keys with the new keys.
$db->assign('user_id', "1");
basically does this:
$this->fields['user_id] = (1)==""?("'1'"):1;
And when you got to do it again, it replaces it
$this->fields['user_id'] = (2)==""?("'2'"):2;
Try doing an assign, and then only assign the user_id again, there rest of the data will stay the same.
To fix this problem, we would call the $this->reset() function after a query.
public function query($_query){
$this->query = $_query;
$this->result = #mysql_query($_query, $this->link_id) or die( $_query."<p>".mysql_error($this->link_id) );
$this->reset();
return $this->result;
}
or you could call it in the individual insert or update functions:
public function insert($table){
// .... stuff
$this->query($sql);
$this->reset();
return $this->insert_id();
}
The other possibility is that the original programmer didn't convey his intent to you well enough. He might expect you to call $db->reset() after every query.

Categories