Order by on EF not working as I had hoped - entity-framework-4.1

How do I get this to work properly? I want order by duedate desc, type
I currently have:
billSummaryRepository.GetBillSummaries(logIn.CustomerNumber)
.OrderByDescending(o => o.DueDate)
.OrderBy(o => o.Type)
This works:
BillSummaries = billSummaryRepository.GetBillSummaries(logIn.CustomerNumber)
.OrderBy(o => o.Type)
.OrderByDescending(o => o.DueDate)
but how dangerous is that? Will it work?

BillSummaries = billSummaryRepository
.GetBillSummaries(logIn.CustomerNumber)
.OrderByDescending(o => o.DueDate)
.ThenBy(o => o.Type);

Related

In the controller do a find specifiing basic conditions but the query built by cakephp doesn't match the conditions

In the controller :
$budget = $this->Budget->find('first',
array('conditions' => array(
"copros_id" => $this->Session->read('Copro.id'),
"typebudgets_id" => $typebudget['Typebudget']['id'],
"exercices_id" => $this->Session->read('Exercice.id'))));
generates the sql:
SELECT `Budget`.`id`,
`Budget`.`created`,
`Budget`.`modified`,
`Budget`.`title`,
`Budget`.`statusbudgets_id`,
`Budget`.`typebudgets_id`,
`Budget`.`copros_id`,
`Budget`.`visible`,
`Budget`.`exercices_id`
FROM `default_schema`.`budgets` AS `Budget`
WHERE `Budget`.`typebudgets_id` = ('466b50a5-4736-11e6-a160-00163ee3b504')
The Model contains :
public $belongsTo = array(
'StatusBudget' => array(
'className' => 'StatusBudget',
'foreignKey' => 'statusbudgets_id'
),
'Exercice' => array(
'className' => 'Exercice',
'foreignKey' => 'exercices_id'
),
'Typebudget' => array(
'className' => 'Typebudget',
'foreignKey' => 'typebudgets_id'
),
'Copro' => array(
'className' => 'Copro',
'foreignKey' => 'copros_id'
),
);
It looks like the conditions in the find are ignored by cakephp (2) when building the query; specifying different conditions in the find give the same sql as a result. As if the conditions don't matter in fact.
Strange (for me).
Thanks
A couple of things may be happening here:
First try to clear the model cache. If you don't know how to use the cake console just delete the files in the /tmp/cache/model folders.
The table behind the Budget model does NOT have the columns you are making a reference to. Or there is a typo in their name. In that case Cake will not use them when you build your conditions.
The db table for budget has all the required columns, but the way the Table class is defined could interfere with properly reading the table structure from the database.
Thinking about Ilia Pandia's answer I tried to specify more precisly my conditions:
$budget = $this->Budget->find('first',
array('conditions' => array(
"Budget.copros_id" => $this->Session->read('Copro.id'),
"Budget.typebudgets_id" => $typebudget['Typebudget']['id'],
"Budget.exercices_id" => $this->Session>read('Exercice.id'))));
The sql generated is now what I expected:
SELECT `Budget`.`id`, ...
FROM `default_schema`.`budgets` AS `Budget`
LEFT JOIN `default_schema`.`status_budgets` AS `StatusBudget` ON (`Budget`.`statusbudgets_id` = `StatusBudget`.`id`)
LEFT JOIN `default_schema`.`exercices` AS `Exercice` ON (`Budget`.`exercices_id` = `Exercice`.`id`)
LEFT JOIN `default_schema`.`typebudgets` AS `Typebudget` ON (`Budget`.`typebudgets_id` = `Typebudget`.`id`)
LEFT JOIN `default_schema`.`copros` AS `Copro` ON (`Budget`.`copros_id` = `Copro`.`id`)
WHERE Budget.copros_id = '5af2bda8-97d0-403a-ad96-4cf1ac171864'
AND Budget.typebudgets_id = '466b50a5-4736-11e6-a160-00163ee3b504'
AND Budget.exercices_id = '5af2c13b-43d0-412f-97d9-4752ac171864' LIMIT 1
Thank you!

CakePHP 3 Paginator using FIELD() in ORDER clause

I have a question regarding the Paginator Component of CakePHP3 (3.0.13). I'm using the MYSQL function FIELD() to order my data, like that:
$this->paginate = array_merge_recursive([
'conditions' => [
'zip IN' => $zips
],
'order' => [
'FIELD(zip, '.rtrim(implode(',', $zips), ',').')',
'ispro' => 'desc',
],
$this->paginate
]);
When I apply this to my $this->paginate() it wouldn't be recognized as long as the query param sort is set. To avoid this I remove the sort in my request with:
if (isset($this->request->query['sort'])) {
unset($this->request->query['sort']);
}
This is working, but I was wondering if there is a better solution, maybe in the paginator component itself, which I haven't found yet.
you can sort your query before you paginate it. Your sort conditions will come before the one appended from the paginator component
so you can do
$dentists = $this->Dentists->find()
->order([
'FIELD(zip, '.rtrim(implode(',', $zips), ',').')',
'ispro' => 'desc'
]);
$this->paginate = array_merge_recursive([
'conditions' => [
'zip IN' => $zips
],
$this->paginate
]);
$dentists = $this->paginate($dentists);

Codeigniter insert double quotes once

Hi I have the following insert:
$full_pjt_save = array(
'img_copertina' => $this->input->post('copertine'),
'physical_already' => $this->input->post('physical_already'),
'physical_format_product' => $this->input->post('formato_fisico'),
'physical_format' => $this->input->post('physical_format'),
'physical_format_vinile' => $this->input->post('formato_vinile'),
'physical_boxqty' => $this->input->post('physical_boxqty'),
'physical_tot_time' => $this->input->post('physical_tot_time'),
'physical_qty' => $this->input->post('physical_qty'),
'sale_price' => $this->input->post('sale_price'),
'keywords' => $this->input->post('keywords'),
'descrizione' => $this->input->post('descrizione'),
'durata' => $this->input->post('durata'),
);
$added_fields = $full_pjt_save+array('last_mod' => time());
$this->db->where('id_acquisto', $this->input->post('id_acquisto'));
$save_full_pjt_to_db = $this->db->update('progetti_'.$pjt_table, $added_fields);
$pjt_table_id = $this->db->insert_id();
This works fine, but I have a dropdown item where 'formato_vinile' is this:
45 Giri (7" Singolo, 45 Giri)
but gets inserted in the db cut after the double-quotes:
45 Giri (7
Is there a way to write it in full?
ok since i cant write it as comment cause of the code... here my idea:
its quick&dirty so you should modificate it a bit.
$added_fields = $full_pjt_save+array('last_mod' => time());
$this->db->where('id_acquisto', $this->input->post('id_acquisto'));
$this->db->set('physical_format_vinile', $this->input->post('formato_vinile'), FALSE);
$save_full_pjt_to_db = $this->db->update('progetti_'.$pjt_table, $added_fields);
$pjt_table_id = $this->db->insert_id();
note to unset/delete the key physical_format_vinile from your $added_fields array
its not tested but i hope it helps or give you an idea how to handle your problem.
*edit lets maybe check where is the exactly problem. can you do a var_dump($this->input->post('formato_vinile')) and check if the double quotes are still correct?
just escape your input $this->input->post(mysqli::escape_string ('formato_vinile'))
Apologies not a static call that was a bit of psuedo code though in CI (I am not a user)
$this->db->escape_str() ;

yii CActiveDataProvider with limit and pagination

I'm trying to select few rows from the table and render it in multiple pages (pagination).
This is a code in the model:
return new CActiveDataProvider('Downloads',
array(
'criteria' => array(
'select' => 'download_id,title,thumb_ext',
'order' => 'download_id DESC',
'limit' => $count,
),
'pagination' => array('pageSize' => 5,),
)
);
In the view I display it using CGridView:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns' => array('download_id', 'title', 'thumb_ext'),
));
The problem is that CActiveDataProvider ignores limit of criteria and returns all rows of table...
Thanks.
I'm not positive... but I think Yii uses the LIMIT clause to do SQL result pagination, so it will overwrite/replace your LIMIT clause. You can check this by turning on the CWebLogRoute log route to see exactly what SQL is being executed.
I'm not quite sure how this is supposed to work, anyway. What is the LIMIT clause you added for? If you are paginating anyway, why not let the user paginate through all the records? The solution is probably to change your criteria to get rid of the LIMIT clause.
Are you trying to set the number of results per page? You already have the pageSize set to 5 though...
One other thing to try that might do what you want, is to check out the base Pager class, CPagination. With CLinkPager, it might let you paginate more creatively than the CListPager you are using with the CGridView.
Good luck!
I had the same problem and I found a solution as follows:
return new CActiveDataProvider('Downloads',
array(
'criteria' => array(
'select' => 'download_id,title,thumb_ext',
'order' => 'download_id DESC',
),
'pagination' => array('pageSize' => 5,),
'totalItemCount' => $count,
)
);
and set CGridView to pagination is hidden:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'enablePagination' => false,
'columns' => array('download_id', 'title', 'thumb_ext'),
));
One of the basic features of a data provider is that you can override the calculation of the amount of rows by specifying a "totalItemCount" in the config. Normally (I haven't tested it) this also works for the ActiveDataProvider:
return new CActiveDataProvider('Downloads',
array(
'criteria' => array(
'select' => 'download_id,title,thumb_ext',
'order' => 'download_id DESC',
),
'pagination' => array('pageSize' => 5,),
'totalItemCount' => $count,
)
);

Cakephp model associastion

I have thee following simple model:
Item belongsTo CatalogItem
CatalogItem hasMany Item, and belongsTo Section
Section hasMany CatalogItem
I'm trying to get counts of items, grouped by catalogitem, for a certain section-
the equivalent of:
SELECT catalogitem.id, count(*) FROM section LEFT JOIN catalogitem ON section.id=catalogitem.section_id LEFT JOIN item ON item.catalogitem_id=catalogitem.id WHERE section.id=5 GROUP BY catalogitem.id
So simple in sql, yet I can't get it to work with cake models. Can anyone point as to how to do it with cake models, using the model->find?
I can't get it to group by correctly or join correctly on 3 tables :(
Edit:
highly prefer to get the info in single query
Here's a longer way, "cakeish" way:
class Item extends AppModel
{
/* snip */
var $virtualFields = array('item_count' => 'count(Item.id)');
function getCountForSection($sectionId)
{
$ca = $this->Catalogitem->find
(
'all',
array
(
'fields' => array('Catalogitem.id'),
'conditions' => array('Catalogitem.section_id' => $sectionId),
'recursive' => -1
)
);
$ca = Set::extract('/Catalogitem/id', $ca);
$ret = $this->find
(
'all',
array
(
'fields' => array('Item.catalogitem_id', 'item_count'),
'conditions' => array('Item.catalogitem_id' => $ca),
'group' => array('Item.catalogitem_id'),
'recursive' => -1
)
);
return $ret;
}
}
Then simply use it in your controller:
$ret = $this->Item->getCountForSection(1);
debug($ret);
How does it work:
Define a virtual field (cake 1.3+ only AFAIK) which will count items
Fetch all the Catalogitems belonging to a Section you're interested in
Use Set::extract() to get the Catalogitems in a simple array
Use the array of Catalogitems to filter Items while counting and grouping them
NB: You don't seem to be using Cake's naming conventions in your database. This may hurt you.
Sorry, in my first answer I somehow missed your GROUP BY requirement, which was the whole point of the question, I now realize. I haven't used this yet, but I came across it recently, and it looks like it might accomplish what you are looking for: Linkable Behavior.
http://planetcakephp.org/aggregator/items/891-linkable-behavior-taking-it-easy-in-your-db
Like Containable, but works with only right and left joins, produces much more compact queries and supports GROUP BY.
http://github.com/rafaelbandeira3/linkable
#azv
Would this work for you:
$section_id = 5;
$fields = array('CatalogItem.id as CatalogItemId', 'count(*) AS SectionCount');
$conditions = array('Section.id' => $section_id);
$joins = array(
array('table' => 'catalogitem',
'alias' => 'CatalogItem',
'type' => 'LEFT',
'conditions' => array('Section.id' => 'CatalogItem.section_id')
),
array('table' => 'item',
'alias' => 'Item',
'type' => 'LEFT',
'conditions' => array('Item.catalogitem_id' => 'CatalogItem.id')
));
$data = $this->Section->find('all',
array('fields' => $fields,
'conditions' => $conditions,
'joins' => $joins,
'group' => 'CatalogItem.id',
'recursive' => -1)
);
// access your data values
foreach ($data['Section'] as $i => $datarow) {
$catalogitem_id = $datarow['CatalogItemId'];
$section_count = $datarow['SectionCount'];
}
This way you are explicitly setting your joins and doing it all in one query. See here for more info on joins in Cake:
http://book.cakephp.org/view/1047/Joining-tables
Hope this helps. All the best,
-s_r