Natural sorting Ajax Datatables in Codeigniter - mysql

Struggling to figure out how to set natural sorting in AJAX Datatables using Codeigniter Active record.
The field that should be sorted has, in most cases, just digits...in other cases a string, so the MySQL table field is set as VARCHAR.
I need to srt naturally the field to be displayed in Datatables.
The Active record Codeigniter query is the following.
function list_all($limit,$start,$col,$dir)
{
$this->rmi_db->select ("
$this->table_dev.id,
$this->table_dev.fl,
$this->table_dev.mm,
$this->table_dev.batch,
$this->table_dev.n,
$this->table_dev.ditta,
$this->table_dev.tipo,
$this->table_dev.costruzione,
$this->table_dev.motori,
$this->table_dev.nc,
$this->table_dev.serie,
$this->table_dev.ca,
$this->table_dev.consegna,
$this->table_dev.matr_usaf AS usaf,
$this->table_dev.matr_usn AS usn,
$this->table_dev.matr_caf AS caf,
$this->table_dev.matr_raf AS raf,
$this->table_dev.codici,
$this->table_dev.note,
$this->table_dev.reg_civili,
$this->table_dev.matricola_civ,
$this->table_dev.prima_reg,
$this->table_dev.n_contratto,
$this->table_dev.data_contratto,
$this->table_dev.importo_contratto,
$this->table_dev.note_contratto,
$this->table_dev.f29,
$this->table_dev.f30,
");
$this->rmi_db->from("$this->table_dev");
$this->rmi_db->where("$this->table_dev.mm !=", "");
$this->rmi_db->limit($limit, $start);
$this->rmi_db->order_by($col, $dir);
$query = $this->rmi_db->get();
if($query->num_rows()>0)
{
return $query->result();
}
else
{
return null;
}
}
The mm field should be sorted naturally. I have no idea how and if it's possible to fix the issue.
I tried the solution in this discussion solutions, the Bin way, but the select doesn't work properly ( got 500 server error)
Thanks a lot for any help

Using Solution, Try below. It should work but not tested.
function list_all($limit,$start,$col,$dir)
{
$this->rmi_db->select ("
$this->table_dev.id,
$this->table_dev.fl,
$this->table_dev.mm,
$this->table_dev.mm, CAST($this->table_dev.mm as SIGNED) AS casted_column,//changed
$this->table_dev.batch,
$this->table_dev.n,
$this->table_dev.ditta,
$this->table_dev.tipo,
$this->table_dev.costruzione,
$this->table_dev.motori,
$this->table_dev.nc,
$this->table_dev.serie,
$this->table_dev.ca,
$this->table_dev.consegna,
$this->table_dev.matr_usaf AS usaf,
$this->table_dev.matr_usn AS usn,
$this->table_dev.matr_caf AS caf,
$this->table_dev.matr_raf AS raf,
$this->table_dev.codici,
$this->table_dev.note,
$this->table_dev.reg_civili,
$this->table_dev.matricola_civ,
$this->table_dev.prima_reg,
$this->table_dev.n_contratto,
$this->table_dev.data_contratto,
$this->table_dev.importo_contratto,
$this->table_dev.note_contratto,
$this->table_dev.f29,
$this->table_dev.f30,
");
$this->rmi_db->from("$this->table_dev");
$this->rmi_db->where("$this->table_dev.mm !=", "");
$this->rmi_db->limit($limit, $start);
$this->rmi_db->order_by($col, $dir);
$this->rmi_db->order_by('casted_column', 'ASC'); // changed
$this->rmi_db->order_by($this->table_dev.mm, 'ASC'); // changed
$query = $this->rmi_db->get(); //changed
if($query->num_rows()>0)
{
return $query->result();
}
else
{
return null;
}
}
comment if you face any issue

Related

Code Igniter - not showing the entry I need

I have the following code to get one line for each MAC with the LATEST state. The problem I have is that I get one line but not with the latest state but rather with the earliest.
function get_active_devices($min_duration, $max_duration)
{
//get all active devices DESC order
$this->db->distinct();
$this->db->group_by('mac');
$this->db->order_by("id", "desc");
$this->db->select('data.mac, state, time, iot_bo.notified, iot_bo.op_state, iot_bo.Name');
$this->db->where('time >', time()-$max_duration);
$this->db->where('time <', time()-$min_duration);
$this->db->join('iot_bo', 'iot_bo.mac = data.mac');
$this->db->where('iot_bo.op_state', '1');
$query = $this->db->get();
return $query;
}
Have you tried the query without the distinct and groupBy first? May be the result you want isn't in the total result set to begin with. Because there doesn't seem to be anything wrong with your use of db methods as it is.

MySQL and using only some results

I am trying to create a directory and having an issue calling the "listing image" in the results. The issue is that only some listings will have images, otherwise if they do not, I want them to use the default-image I have set up. When I try and add in the 'image' table to my query, it returns ONLY the results that have an image available (leaving out the other listings that do not have an image).
Here is my code:
public function search($neighborhood = null, $biz_filter = null) {
$neighborhood = $this->uri->segment(3);
$biz_filter = $this->uri->segment(4);
// SELECT
$this->db->select('*');
// MAIN TABLE TO GRAB DATA
$this->db->from('biz');
// TABLES TO JOIN
$this->db->join('city', 'city.city_id = biz.biz_cityID');
$this->db->join('zip', 'zip.zip_id = biz.biz_zipID', 'zip.zip_cityID = city.city_id');
$this->db->join('state', 'state.state_id = city.city_stateID');
$this->db->join('neighborhood', 'neighborhood.neighborhood_id = biz.biz_neighborhoodID');
$this->db->join('biz_filter', 'biz_filter.bizfilter_bizID = biz.biz_id');
$this->db->join('biz_category', 'biz_category.bizcategory_id = biz_filter.bizfilter_bizcategoryID');
if ($neighborhood != "-" AND $biz_filter != "-") {
$this->db->where('biz_category.bizcategory_slug', $biz_filter);
$this->db->where('neighborhood.neighborhood_slug', $neighborhood);
} elseif ($neighborhood != "-" AND $biz_filter == "-") {
$this->db->where('neighborhood.neighborhood_slug', $neighborhood);
} elseif ($neighborhood == "-" AND $biz_filter != "-") {
$this->db->where('biz_category.bizcategory_slug', $biz_filter);
} else {
}
// ORDER OF THE RESULTS
$this->db->group_by('biz_name asc');
// RUN QUERY
$query = $this->db->get();
// IF MORE THAN 0 ROWS ELSE DISPLAY 404 ERROR PAGE
return $query;
}
How can I add in the separate table, 'image' that holds the logo images ('image.image_file'). The 'image' table and 'biz' table are connected through the business ID i pass through each table (image.biz_id = biz.biz_id).
Anyone know how to resolve the query to work properly?
Just use
$this->db->join('image', 'image.biz_id = biz.biz_id', 'left');
To LEFT JOIN your image table. When there is no records in the table for the biz_id the image.image_file will have null values. Read here for more information.
You can use a COALESCE function to replace the "null" images with a predefined default value. Just replace your line with $this->db->select('*'); to this one:
// SELECT
$this->db->select("*, COALESCE(image.image_file, 'images/not_found.png') as my_image_file");
When you render the output make sure you use my_image_file column for the image.
On a side note: avoid using '*' in the select. Select only those columns you actually need. Selecting all columns unnecessarily increases the load on the database server resources.

Laravel - How to paginate here?

I have this code and I want to paginate $shares.
How can I archive this?
$level = Share::join('follows', 'shares.user_id', '=', 'follows.user_id')
->where('follows.follower_id', Auth::user()->id)
->where('follows.level', 1)
->get(array('shares.*'));
//get 10% of shares
$count = Share::count()/10;
$count = round($count);
$top10 = Share::orderBy('positive', 'DESC')
->take($count)
->get();
$shares = $top10->merge($level);
//get only unique from shares
$unique = array();
$uniqueShares = $shares->filter(function($item) use (&$unique) {
if (!in_array($item->id, $unique)) {
$unique[] = $item->id;
return true;
} else {
return false;
}
});
//order by id
$shares = $uniqueShares->sortBy(function($share)
{
return -($share->id);
});
return View::make('layout/main')
->with('shares', $shares);
lots of reudandant unnecessary codes here.
1st:
$level = Share::join('follows', 'shares.user_id', '=', 'follows.user_id')
->where('follows.follower_id', Auth::user()->id)
->where('follows.level', 1)
->get(array('shares.*'));
Why you are taking ALL the records only to discard it later?
2nd:
$shares = $top10->merge($level); Why you are merging the two arrays?
3rd:
$uniqueShares = $shares->filter(function($item) use (&$unique) {
if (!in_array($item->id, $unique)) {
$unique[] = $item->id;
return true;
} else {
return false;
}
});
You HAD to wrote this snippet because above in 2nd, you merged the two arrays which will yield duplicated entries. So why merging?
4th:
//order by id
$shares = $uniqueShares->sortBy(function($share)
{
return -($share->id);
});
And here comes the actual data which you actually want.
So let's recape
You need
10% of total shares
order by some positive column
order by amount of shares perhaps as i am guessing.
To use the inbuilt paginate(), you'l need paginate() that's a must.
Rest is simple.
count the total result. round(Share::count()/10)
put it in paginate() as the 1st arguement.
Add the order by clause whichever is necessary.
looking at the code, it doesn't look like you will/should have duplicated data which may haved added the distinct and group by clause.
use remember in Share::count()/10; to Cache it. You don't need to run the query over and over again.
and you're done.
The way you are merging your queries you may need to manually create it the pagination in your blade, then send a variable to "take" the next set you want.
Read the Laravel Docs for more info on implementing it into your views and manually creating it.
http://laravel.com/docs/pagination
Try this, should be good to go
Share::join('follows', 'shares.user_id', '=', 'follows.user_id')
->where('follows.follower_id', Auth::user()->id)
->where('follows.level', 1)
->paginate(20);
Maybe you would like to specify columns to select in select() method.

Magento: Subtraction and Division on addAttributeToFilter

I'm a newbie with Magento getResourceModel, and I'm trying to add a simple filter to my query, but i can't figure that using getResourceModel.
Original Query:
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$collection->addAttributeToFilter('promotion', 1)->setOrder('price', 'desc');
I just want add the where clause:
(`price` - `final_price`) >= (`price` * 0.4)
Someone can help me to do this?
This is all, thanks!
So finally I found the correct way to do this, sorry to delay to post the answer here and thanks #feeela.
Looking the file /lib/Zend/Db/Select.php I found that exists the where function:
public function where($cond, $value = null, $type = null)
{
$this->_parts[self::WHERE][] = $this->_where($cond, $value, $type, true);
return $this;
}
So, what we need is just add a call to this function giving the condition that we want. In my case, I just add a condition to filter products that have 40% of discount.
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$collection->addAttributeToFilter('promotion', 1)
->addStoreFilter();
$collection->getSelect()->where( '(`price` - `final_price`) >= (`price` * 0.4)' );
So, I hope that this can be helpful for some dudes!
Grazie tutti!

mysql_affected_rows() always returns 1 even though no row was updated

What I am trying to do is: (programmatically)
Update status where id is something, if no rows where updated, give error: we cannot find the record with id something, otherwise give message success.
Here I am using mysql_affected_rows() to know if a row was updated or not, but it always return 1, so the user gets a success message, even though there was no row updated.
Can anyone tell me what could it be?
Here's the code:
function update_sql($sql) {
$this->last_query = $sql;
$r = mysql_query($sql);
if (!$r) {
$this->last_error = mysql_error();
return false;
}
$rows = mysql_affected_rows();
if ($rows == 0) return true; // no rows were updated
else return $rows; }
This code returns 1.
That is because true will print out as "1" if you use echo. For debugging try using var_dump(), or let your function return 0 (which seems to me, in this case, the better option).
One little note; I think you should try to make your code a bit more readable (if the code in your question has the same layout as the code in your file). Try to indent code blocks, use separate lines for closing curly brackets, etc...
This is just a guess...
Maybe your function works as excepted? Maybe this piece of code if ($rows == 0) return true; works fine, and returns true but you treat that value as integer (boolean true can be displayed as 1)? Do: var_dump(uddated_sql('YOUR QUERY')) and check whether it returns boolean true or integer 1 value.