Codeigniter Database Record retrival - Best Practise - Performance - php

I'm checking an PHP project which is build using PHP Codeigniter. I'm new to PHP, I like to get your valuable feedback
To retrieve name and item number in php library/controller, call is made to Item Model as below
'name'=>$this->CI->Item->get_info($item_id)->name
'item_number'=>$this->CI->Item->get_info($item_id)->item_number
I suspect above two line of code will make two independent database sql call instead of one call to retrive the two column of same table. Ie., there will be performance degrade. But somebody can please let me know whether it fires two sql statements please?
I think we need to handle like object
$row = $this->CI->Item->get_info($item_id);
echo $row->name;
echo $row->item_number;
Please suggest. Thanks in advance.
Model Function:
function get_info($item_id)
{
$this->db->from('items');
$this->db->where('item_id',$item_id);
$query = $this->db->get();
if($query->num_rows()==1)
{
return $query->row();
}
else
{
//Get empty base parent object, as $item_id is NOT an item
$item_obj=new stdClass();
//Get all the fields from items table
$fields = $this->db->list_fields('items');
foreach ($fields as $field)
{
$item_obj->$field='';
}
return $item_obj;
}
}

Related

Optimize Query on Models

I have a problem with displaying a bunch of data from my database. Getting data from many tables.
My query before was getting all the data in one query then I had managed to find a way on how to optimize it but I'm not satisfied.
foreach($query->result_array() as $row ){
$drreturn = $this->getDRReturnAmount($row["idno"],$date1);
$return_amount[] = $drreturn->return_amount;
$checkDRServiceNoPayment = $this->checkDRServiceNoPayment($row["idno"],$date1,$date2);
if($checkDRServiceNoPayment->num_rows() > 0) {
$minus_item_amount[] = 0;
$getProductPurchase = $this->getProductPurchase($row["idno"],$date1,$date2);
$minus_item_amount[] = $getProductPurchase->amount;
}
}
btw I'm using datatable. what I did before was I didn't use an array and I put the model functions inside the foreach but it seems that nothing happened even tho I used array.

CodeIgniter MVC and Looping through a MySQL table

I'm trying to create a iterate through a row in a MySQL table in one of my CodeIgniter projects, how could I "loop" through the table? Is it just a simple for loop like in other languages?
EDIT:
The answer is as followed:
$query = $this->db->get('mytable'); // select table "mytable" from database
foreach ($query->result() as $row) { // loop thru table and access each row's field
// by using $row->fieldname
}
Maybe something like this
//$this->db->limit(10); // Optional if you want to limit, read about it
$result = $this->db->get('server'); //return all rows
foreach ($result as $row) {
$row->status = 'inactive'; // change value of status attribute or whatever
$this->db->update('server', $row)
}
Or maybe use $this->db->update_batch(); to update a stack of rows at one time.
I encourage you to read the CI database class documentation too.
Another suggestion, is to do all the business logic inside a model instead of a controller. But it's a matter of personal preference maybe.

Generic fast coded PHP MySQL dynamic insert/update query creating table/fields named as variables if doesnt exists

I'm looking for a way to make MySQL insert/update queries more dynamic and fast to code since sometimes one just need another field in a form (when for example prototyping an application). This might be a dumb question.
My idea is to make an insert or update if ids match, and if table/fields doesn't exists create it with one function dynamically.
<?php
// $l is set with some db-login stuff
// creates and inserts
$f[] = nf(1,'this_id_x'); // this_id_* could be a prefix for ids
$f[] = nf('value yep',$fieldname_is_this2)
$tbl_name = "it_didnt_exist";
nyakilian_fiq($l, $tbl_name, $f);
// Done!
//This would do an update on above
$fieldname_is_this2 = "this is now updated";
$f[] = nf(1,'this_id_x');
$f[] = nf($fieldname_is_this2); // the function takes the variable name as field name
$tbl_name = "it_didnt_exist";
nyakilian_fiq($l, $tbl_name, $f);
?>
I have been using this function with success. It doesn't add a column but that is against the structure of my MVC framework. Try something like this:
public function save(DatabaseConnection &$db)
{
$properties = get_object_vars($this);
$table = $this->getTableName();
// $cols = array();
// $values = array();
foreach ($properties as $key => $value) {
$cols[] = "`$key`";
$values[] = '"'.$value.'"';
if ($value != NULL) {
$updateCols[] = "`$key`".' = "'.$value.'"';
}
}
$sql = 'INSERT INTO '.$table.' ('.implode(", ", $cols).') VALUES ('.implode(", ", $values).') ON DUPLICATE KEY UPDATE '.implode(", ", $updateCols);
$stmnt = $db->prepare($sql);
var_dump($stmnt);
if ($stmnt->execute($values)) return true;
return false;
}
I have a model abstract class that I extend with a child class for each database table. This function sits in the model abstract. Each child class contains a public property [so I can use PDO::fetchObject()] that corresponds to a column name in the table. If I need to create the table on the fly, I add a function to the child class to do so.
This is quite unusable approach.
You are trying to mix into one single function (not even a class(!) a functionality that fits for a decent framework. That's just impossible (or unusable for some parts).
Yet it resembles major frameworks' Models in many aspects.
So, I could give just some recommendations
Do not create tables dynamically. Data structure is a backbone of the application and have to be solid.
do not take too much considerations (like "If an ID is passed"). it will tie your hands for whatever more complex case
take a look at some major frameworks - it seems your wishes are already fulfilled with their codegeneration feature (an ugliest thing that ever existed on the Erath in my private opinion). They're working pretty the same way you're talking about: you have to only define a Model and the rest is done by framework's methods

Unsure as to how certain sections of this function work

While writing a login system for a web project Im working on I came across the problem of binding an unknown number of parameters and found this function on the php manual pages. I always like to fully understand an peice of code I put into anything Im working on and Im quite stumped as to how a few sections of this function work.
Ive commented everything I think i understand(if im wrong please let me know) and left my major questions in the comments:
<?php
function getresult($stmt) {
//Define var for holding the result
$result = array();
//asign metadata of the statments result
$metadata = $stmt->result_metadata();
//grab the feilds from the metadata and assign to var
$fields = $metadata->fetch_fields();
//for loop with internal break
for (;;) {
//pointers array (not sure why this is an array and not a stdClass)
$pointers = array();
//row empty class
$row = new stdClass();
//set pointers array to the value of the passed statement (casting $pointers to mysqli_stmt class I assume(?)
$pointers[] = $stmt;
//iterate through all fields
foreach ($fields as $field) {
//each time set $fieldname to the name from the current element of $fields
$fieldname = $field->name;
//?? this is my big issue no idea whats going on here $row hasnt been set from what i can see, and no idea why its being refered to by reference and not value
$pointers[] = &$row->$fieldname;
}
//call bind result for all values
call_user_func_array(mysqli_stmt_bind_result, $pointers);
//internal break if
if (!$stmt->fetch()) {
//if there is nothing left to fetch break
break;
}
//set the result
$result[] = $row;
}
//free resources
$metadata->free();
//return result
return $result;
}
?>
Thanks in advance!
It creates a new stdClass (pretty much like an empty array) for each row.
With $pointers[] = &$row->$fieldname; a reference to the various fields of the object is stored.
After that, mysqli_stmt_bind_result is used to tell mysqli where to store the data of the next row. When calling $stmt->fetch(), mysqli assigns it to the references in $pointers and thus to the fields in the $row object.
$pointers is an array because mysqli_stmt_bind_result expects one. Objects do not have 0..n fields but rather named values - so to assign columns based on their position using a non-associative array makes much more sense.
It does pretty much the same what mysqli::fetch_object() does.

PHP mySQL - Can you return an associated array with a number index?

I have this method in my db class
public function query($queryString)
{
if (!$this->_connected) $this->_connectToDb(); //connect to database
$results = mysql_query($queryString, $this->_dbLink) or trigger_error(mysql_error());
return mysql_num_rows($results) > 0 ? mysql_fetch_assoc($results) : false;
}
This works great for queries that return 1 row, but how can I get an array returned something like this?
$array[0]['name'] = 'jim'
$array[0]['id'] = 120
$array[1]['name'] = 'judith'
$array[1]['ID'] = 121
Now I know I could use a while loop to insert this data into the array like so, but I was wondering if PHP could do this with an internal function? I havn't been able to find on the docs what I'm after.
The reason I don't want to run the while within the method is because I am going to reiterate back over the array when it's returned, and I'd rather not run through the results twice (for performance reasons).
Is there a way to do this? Do I have a problem with my general query method design?
Thank you muchly!
public function query($queryString)
{
if (!$this->_connected) $this->_connectToDb(); //connect to database
$results = mysql_query($queryString, $this->_dbLink) or trigger_error(mysql_error());
$data = array();
while($row = mysql_fetch_assoc($results))
{
$data[] = $row;
}
return $data;
}
this will always return an array.
EDIT:
I didn't read the question well.
If you realy don't want to use the loop then I would do this:
public function query($queryString)
{
if (!$this->_connected) $this->_connectToDb(); //connect to database
return mysql_query($queryString, $this->_dbLink) or trigger_error(mysql_error());
}
then loop over it, however I would just use the loop.
You might also want to look at the PDO extension. You can load the entire result set into an array or you can loop using foreach.
<?php
$db = new PDO($connection_string, $username, $password);
$result = $db->query($queryString);
foreach($result as $row) {
// do something
}
// or
$result = $db->query($queryString);
$result_array = $result->fetchAll(PDO::FETCH_ASSOC);
?>
Most people use a while() loop in the query to do exactly what you want and then loop over the array to process it.
However, you're right: it wastes memory, which could be a problem with a large dataset. An alternative is for your query method to return the resultset resource. Then your while loop can use that to fetch each row as it requires it.
To abstract that away, I would suggest another class to do that for you. Then your query call would return a new instance of that class which has the MySQL resultset resource as an instance variable and packages up the mysql_fetch_assoc() call.
Look at PEAR::MDB2 (Quickstart Cheatsheet). It provides lots of different functions for doing something like this. It also does not tie you down into using MySQL specific functions because it is a database abstraction layer.
$result = $db->queryRow($query, MDB2_FETCHMODE_ASSOC);
There are other abstraction layers such as ADO as well.
thanks for the ideas. I have a function that returns an associative array from the sql (used in Moodle).
$results = get_records_sql($sql);
//to create a numerically indexed array:
$data = array();
foreach ($results as $row)
{
$data[] = $row;
}
return $data;
}

Categories