How do I set order by field when using fuelphp orm's has many? - orm

I'm using fuelphp's orm to model my data. How can I control which order my child elements are returned when doing a cascaded find.
For example, here's the example config to attach comments to a post:
protected static $_has_many = array(
'comments' => array(
'key_from' => 'id',
'model_to' => 'Model_Comment',
'key_to' => 'post_id',
'cascade_save' => true,
'cascade_delete' => false,
)
);
How can I say, for example, order the comments by the 'date_entered' field?
Thanks in advance,
David

You can add the order_by clause to the conditions.
protected static $_has_many = array(
'comments' => array(
'key_from' => 'id',
'model_to' => 'Model_Comment',
'key_to' => 'post_id',
'cascade_save' => true,
'cascade_delete' => false,
'conditions' => array(
'order_by' => array(
'field1' => 'DESC',
'field2' => 'ASC',
)
),
),
);
Note that as they are defined in the relation, they are always active and can not be turned off!

Related

F3 Cortex and Many to Many relation

I'm building a simple app using F3 and Cortex but I'm running in some problems trying to create a simple Many to Many relation. Its just two tables (and a third, from the relation), the tables already exist and have some data:
class User extends \DB\Cortex {
protected
$fieldConf = array(
'name' => array (
'type' => 'VARCHAR128',
'nullable' => false,
'required' => true,
),
'email' => array (
'type' => 'VARCHAR256',
'nullable' => false,
'required' => true,
),
'password' => array (
'type' => 'VARCHAR128',
'nullable' => false,
'required' => true,
),
// 'groups' => array(
// 'has-many' => array('Group', 'group_id', 'user_has_group')
// )
),
$db = 'db',
$table = 'user';
}
and
class Group extends \DB\Cortex {
protected
$fieldConf = array(
'name' => array(
'type' => 'VARCHAR128',
'nullable' => false,
'required' => true,
),
'description' => array(
'type' => 'VARCHAR128',
'nullable' => false,
'required' => true,
),
// 'users' => array(
// 'has-many' => array('User', 'user_id', 'user_has_group')
// )
),
$db = 'db',
$table = 'group';
}
accourind with this model of the database
But if I remove those comment marks, I get a strange error while acessing anything:
Internal Server Error
No valid DB Connection given.
And on refresh:
Internal Server Error
Fatal error: Leaked 1 hashtable iterators
It looks silly, but I searched all over and spent the better part of a whole day, and still can't seem to make it work.

Prestashop - calculated field in backoffice table form

I would like to add a "virtual" field to a Prestashop 1.6 custom table in the back office. The field indice_calculo_pvp2 should not be saved into the database, as it is a calculated from the values of indice_calculo_pvp and precio_venta_recomendado. What would be the correct way to implement this?
My code is as follows :
public function renderList() {
$this->addRowAction('edit');
$this->addRowAction('delete');
$this->fields_list = array(
'id_product_price' => array(
'search' => false,
'title' => 'ID'
),
'precio_coste' => array(
'title' => 'Precio coste',
'search' => false,
'callback' => 'callback_format_price',
'suffix' => '€'
),
'indice_calculo_pvp' => array(
'title' => 'Indice de cálculo PVP',
'search' => false,
'callback' => 'callback_format_price',
'suffix' => '%'
),
'indice_calculo_pvp2' => array(
'title' => 'Indice de cálculo PVP2',
'search' => false,
'callback' => 'callback_calculate_pvp',
'suffix' => '%'
),
'precio_venta_recomendado' => array(
'title' => 'Precio de venta recomendado con IVA',
'search' => false,
'callback' => 'callback_format_price',
'suffix' => '€'
)
);
return parent::renderList();
}
Use calculation in your SQL SELECT query for the list. I don't know what your calculation formula and your SELECT query is but example of this:
$this->_select = 'a.indice_calculo_pvp / a.precio_venta_recomendado AS indice_calculo_pvp2';
You have 2 options:
You can use a callback function as in your code:
public function callback_calculate_pvp($id, $tr)
{
return $tr['indice_calculo_pvp'] * $tr['precio_venta_recomendado'];
}
You can use a virtual column in your field list indice_calculo_pvp2 and set the value in your SQL query or in getList override function (as ProductController do with price).
Good luck.

CakePHP use JOIN in find method

i am newbie in cakephp and trying to implement this query
SELECT DISTINCT textmessage.mobileNo FROM textmessage
JOIN contacts
ON textmessage.User_id=contacts.User_id AND textmessage.mobileNo = Contacts.mobileNo
i am expecting only one result here .. want to implement this query in textMessage Controller ... i have never use join query before in CAKEPHP... i have actually a mobileNo field in both the tables and i want to retrieve the mobileNo if the mobileNo of textmessage table is also in Contacts table
here is what i have modified your query according to my requirments ..
$this->bindModel(array('belongsTo' => array('Contact' => array('className' => 'Contact',
'foreignKey' => false,
'conditions' => array('Message.user_id = Contact.user_id','Message.mobileNo = Contact.mobileNo')))), true);
return $message_details = $this->find('all', array('conditions' => array(),
'fields' => array('DISTINCT mobileNo')));
Put the following code in your controller's code:
If you need only single record:
function test1()
{
$this->TextMessage->bindModel(array('belongsTo' => array('Contact' => array('className' => 'Contact',
'foreignKey' => false,
'conditions' => array('TextMessage.user_id = Contact.user_id')))), false);
$message_details = $this->TextMessage->find('all', array('conditions' => array(),
'fields' => array('DISTINCT mobileNo')));
}
If you have multiple text messages corresponding to each contact then try the following:
function test2()
{
$this->Contact->bindModel(array('hasMany' => array('TextMessage' => array('className' => 'TextMessage',
'foreignKey' => false,
'conditions' => array('TextMessage.user_id = Contact.user_id'),
'fields' => array('DISTINCT mobileNo')))
), false);
$message_details = $this->Contact->find('all', array('conditions' => array()));
}
You can also write the association in your model. I gave you an example to dynamically join any table on the fly.
According to your edited question, if you don't need two arrays. Use query() function.
Hope this will fulfill your requirement.

How to use CakePHP to do a query bounded by data in two indirectly-related tables

Presume the Query works:
SELECT
users.id,
subscriptions.name,
users.user_type
FROM users
LEFT JOIN users_subscriptions
ON users.id = users_subscriptions.user_id
LEFT JOIN subscriptions
ON users_subscriptions.subscription_id = subscriptions.id
WHERE
subscriptions.name = 'advertisers'
AND
users.user_type = 'agent';
How do I do this in a single Query using cakePHP 1.3?
EDIT: Are joins the right approach?
Yes joins are just fine. Just make sure that you add on the fly before searching to your User model a hasOne to UsersSubscription and to the UsersSubscription model as belongsTo Subscription. Then use the containable behavior to include 'UserSubscription' => 'Susbcription'
Your code might look like this:
$this->User->bindModel(array('hasOne' => array('UserSubscription')));
$this->User->UserSubscription->bindModel(array('belongsTo' => array('Subscription')));
$results = $this->User->find('all', array(
'contain' => array(
'UserSubscription' => 'Subscription'
)
));
You can set up the query the "CakePHP way" like this:
$conditions = array(
'Subscriptions.name' => 'advertisers',
'Users.user_type' => 'agent'
);
$joins = array(
array(
'table' => 'users_subscriptions',
'alias' => 'UsersSubscriptions',
'type' => 'LEFT',
'conditions' => array(
'UsersSubscriptions.user_id=Users.id'
)
),
array(
'table' => 'subscriptions',
'alias' => 'Subscriptions',
'type' => 'LEFT',
'conditions' => array(
'Subscriptions.id=UsersSubscriptions.subscription_id'
)
)
);
$fields = array(
'Users.id', 'Users.user_type', 'Subscriptions.name'
);
$options = array(
'conditions' => $conditions,
'joins' => $joins,
'fields' => $fields
);
$results = $this->Users->find('all', $options);

Populating CGridView one to many relation

In my project one of the model named types having multiple relation to other models the criteria with part is giving below its like
$criteria->with = array(
'category',
'subCategory',
'accountsSupplierPriceDetails' => array(
'with' => 'serviceLevel'
)
);
the relationship goes like
types - category - relation(1-1)
types - subcategory - relation(1-1)
types - accountsSupplierPriceDetails - relation(1-1)
accountsSupplierPriceDetails - serviceLevel - relation(1-n)
my problem is how to display the names from each table in a grid. the result of (1-n) should be displayed in a dropdownbox. when i try to access the data from column it shows the error Trying to get property of non-object ($data->accountsSupplierPriceDetails->serviceLevel ->name). can anyone please help me.
Thanks in advance.
in my view i create a cgridview with 5 rows in which one row data is populated using dropdownlist.
<div style="width:700px; height:auto;">
<?php
$widget = $this->widget('zii.widgets.grid.CGridView', array(
'id' => 'response-grid',
'dataProvider' => $pickdataset->pickCategorylistingForMain(),
'cssFile' => Yii::app()->baseUrl . '/media/css/gridview.css',
'summaryText' => '',
'ajaxUpdate' => 'response-grid',
'enablePagination' => true,
'pager' => array(
'class' => 'LinkPager',
'cssFile' => false,
'header' => false,
'firstPageLabel' => 'First',
'prevPageLabel' => 'Previous',
'nextPageLabel' => 'Next',
'lastPageLabel' => 'Last',
),
'columns' => array(
array(
'name' => 'id',
'header' => '#',
'value' => '$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
),
array(
'type' => 'raw',
'name' => 'categoryExt',
'header' => 'Category',
),
array(
'type' => 'raw',
'header' => 'Sub Category',
'value' => '$data->subCategory->name',
),
array(
'type' => 'raw',
'name' => 'locationExt',
'header' => 'Location',
),
array(
'type' => 'raw',
'header' => 'Name',
'value' => 'CHtml::dropDownList($data->corporate_id."-".$data->category_id."-".$data->sub_category_id."-".$data->location_id,"",popDropBox($data->masterCategoryServiceLevels), array("class" => "listbox"), array("empty" => "Select a Location"))',
),
array(
'type' => 'raw',
'header' => 'Pick',
'value' => 'CHtml::image(Yii::app()->baseUrl . "/media/images/edit_icon.png",$data->corporate_id."-".$data->category_id."-".$data->sub_category_id."-".$data->location_id,array("title" => "Select this Combination"))',
),
),));
function popDropBox($data)
{
$list = array();
foreach ($data as $row)
{
$list[$row->serviceLevel->id] = $row->serviceLevel->name;
}
return $list;
}
?>
</div>
the relation in model is:
'masterCategoryServiceLevels' => array(self::HAS_MANY, 'MasterCategoryServiceLevel', 'category_template_id'),
'corporate' => array(self::BELONGS_TO, 'AccountsCorporate', 'corporate_id'),
'category' => array(self::BELONGS_TO, 'MasterCategory', 'category_id'),
'subCategory' => array(self::BELONGS_TO, 'MasterCategory', 'sub_category_id'),
'location' => array(self::BELONGS_TO, 'MasterLocation', 'location_id'),
the row is
array(
'type' => 'raw',
'header' => 'Name',
'value' => 'CHtml::dropDownList($data->corporate_id."-".$data->category_id."-".$data->sub_category_id."-".$data->location_id,"",popDropBox($data->masterCategoryServiceLevels), array("class" => "listbox"), array("empty" => "Select a Location"))',
),
and i use a function to create dropdown data is
function popDropBox($data)
{
$list = array();
foreach ($data as $row)
{
$list[$row->serviceLevel->id] = $row->serviceLevel->name;
}
return $list;
}
please comment if you have any doubt. i am free to share... have a nice day SO friends... wishes and prayers.