I'm attempting to sort a resulting set by a related table value, in this case a content.created_at value.
The content table is withJoined to my items table properly but in the query I'm attempting to simply sort by that joined table value.
return new ActiveDataProvider([
// Slightly adjusted for clarity as this has some other things in other files:
'query' => ActiveQuery::find()->joinWith(['content']),
'sort' => [
// This throws the error and is unable to resolve `content`
'defaultOrder' => ['`content`.`created_at`' => SORT_ASC]
],
]);
I'm very new to yii and incredibly rusty with php.
How do you setup the sort to look at a joined table value?
Related
I have created a new extension with the extension builder which includes some tables and inline relations between some tables.
For reporting I need some queries where the selection condition is based on the related records.
Here I have difficulties to get the data (except doing raw queries, which seems wrong).
attempt:
do the query in the related records and extract the field which holds the uid of the parent records.
Problem: in the query result is no field with the uid of the parent record (although it is in the database).
This is understandable as there are no methods to get/set the relation. (But it does not change if I insert these methods.)
Also in the children record there is no TCA definition of the relation field except:
'parent' => [
'config' => [
'type' => 'passthrough',
],
],
which might be the reason the field can not be displayed in the record even if inserted in the showitem list.
attempt:
doing a join from the parent record.
Here I have not found any examples how to build a join.
There are other possibilities for a query, but the plainest seems this in the parent record repository:
public function getParentsByFilter($mainCondition,$subCondition) {
$parentQuery = $this->createQuery();
$parentQuery->matching(
$parentQuery->logicalAnd(
$parentQuery->equals('parent_field',$mainCondition)
// $childQuery->equals('children_field',$subCondition)
)
);
// $parentQuery->joinTable('tx_myext_domain_model_children', ...)
$parentQuery->setOrderings(['crdate'=> QueryInterface::ORDER_DESCENDING]);
$parentQuery->getQuerySettings()->setRespectStoragePage(false);
return $parentQuery ->execute();
}
Here I don't know how to join the children table.
I expect some methods like the commented lines, but have not found anything like it.
What's about the same configuration like in the table sys_category?
I have two data sources
1) Database
2) Memcached or Totally different database
From 1st database I am getting the group members list IDs ( has more than 10 thousand rows) and after getting the list I query second database or hit Memcached to get the actual details
$connection = Yii::app()->db;
$sql = 'select user_id,joined_date from group_data where group_id=:group_id ';
$dataProvider = new CSqlDataProvider($sql, array(
'keyField' => 'user_id',
'sort' => array(
'attributes' => array(
'user_id',
'joined_date'
),
'defaultOrder'=>array(
'user_id ASC',
)
),
'pagination' => array(
'pageSize' => 30,
),
'totalItemCount' => $count,
));
$connection_master = Yii::app()->masterdb;
In the above data provider , I am not sure how to include my second database and get the actual user name since it is in other database .No direct connection from one database to other.
Here the problem is pagination is based on the first database table ( 30 records per page) and the actual data is from second table .
Any idea on how to implement this ?
Thank You
You could build your own custom data provider class. You can extend it from CDataProvider and implement the missing abstract methods:
abstract protected function fetchData();
abstract protected function fetchKeys();
abstract protected function calculateTotalItemCount();
Notice, that your storage model already comes very close to these methods: You store the IDs in one database and the actual data in another. So you can focus on one DB at a time in each of these methods.
You'd start with fetchKeys(). There you need to query the keys (=IDs) from your second database. Have a look at CSqlDataProvider::fetchData() to see how to use the CPagination object from $this->getPagination() to find out the current limit and offset. If you need sorting you'd also inspect the CSort object from $this->getSort() for current sort settings. With all that data available you should be able to build the query for the IDs on the currently requested result page.
Then in fetchData() you can obtain those keys through $this->getKeys(). You should not call fetchKeys() directly, because with getKeys() the result from fetchKeys() is "cached", so if it's called again later in the same request, there won't be another query. With that keys you now can easily query your main database. The result will represent the rows on the current page.
Finally you have to implement calculateTotalItemCount(). This is very easy again: Just query your second DB for the total number of items.
That's all you need to do - the code in the base CDataProvider class will take care of the rest and call your methods on demand.
I'm using giix to extend model (and crud) behavior. In this I would like to handle columns of type timestamp (that already exist in my model) specifically, rather like autoincrement fields are handled. (Ignored and not shown, that is.) However, there is no property $column->isTimestamp. I would like to add this somewhere, but I'm rather at loss what the best place for this would be. Do I put it in giix somewhere, or do I have to extend the column-baseclass?
Edit: I want to ignore them from every view, for every table. Since this is a lot of work, and it's something I always want, I'd like to automate it. Adapting the generators seems to make most sense, but I'm not sure what the best way to do it would be.
Here is the process:
Extend your database schema, if you are on MySQL it is CMysqlSchema.
Extend CMysqlColumnSchema and add a "isTimestamp" attribute.
In your CMysqlSchema sub-class extend createColumn and test for a timestamp, you'll see that Yii makes simple string comparisons here to set it's own flags. Set "isTimestamp" in your CMysqlColumnSchema here.
Tell Yii to use your schema driver like this in your components section in the config:
'db' => array(
'connectionString' => 'mysql:host=localhost;dbname=database',
'username' => '',
'password' => '',
'driverMap' => array('mysql' => 'CustomMysqlSchema'),
),
You will need to query the column schema, I've not used giix but find where it is generating the views, it should be looping through either the model attributes or the underlying table schema.
If it is looping through the schema:
//you can also ask Yii for the table schema with Yii::app()->db->schema->getTable[$tableName];
if ('timestamp' === $tableSchema->columns[$columnName]->dbType)
continue; //skip this loop iteration
If it loops over the attributes:
$dbType = Yii::app()->db->schema->getTable[$model->tableName]->columns[$modelAttribute]->dbType;
if ('timestamp' === $dbType)
continue; //skip this loop iteration
I have an error "The column 'Translat2_' was specified multiple times for 'query'" when using paging for my query.
My classes hierarchy:
Politician
--PoliticianInFactions : PoliticianInFaction
--EntityTranslations : Translation
Faction
--PoliticiansInFaction : PoliticianInFaction
--EntityTranslations : Translation
Translation
--Name : String
--Language : Language
What I want: to fetch politicians ordered by its faction's name and than by its name.
My query:
var criteria = Session.CreateCriteria<Politician>("politician");
// criteria for current faction
var currentFactionCriteria = criteria
.CreateCriteria<Politician>(x => x.PoliticianInFactions, JoinType.InnerJoin)
.Add<PoliticianInFaction>(x => x.FromDate <= DateTime.Now)
.CreateCriteria<PoliticianInFaction>(x => x.Faction, JoinType.InnerJoin);
// add order by faction's name !!!
currentFactionCriteria
.CreateCriteria<Faction>(x => x.EntityTranslations, JoinType.InnerJoin)
.Add<Translation>(x => x.Language.Id == languageId)
.AddOrder<CityTranslation>(x => x.Name, Order.Asc);
// add order by politician's name !!!
criteria
.CreateCriteria<Politician>(x => x.EntityTranslations, JoinType.InnerJoin)
.Add<Translation>(x => x.Language.Id == languageId)
.AddOrder<Translation>(x => x.Name, Order.Asc);
When adding paging to this query I have an error. Without paging everything is OK. Also if I comment(remove) any block marked with (!!!) exception dissapears.
What am I doing wrong? If this is a bug of NHibernate give me some workaround please. Thank you.
Check you mapping files to see if you have mapped multiple properties to the same database column or mapped the same databases column to multiple properties.
I know that this is an ancient thread, but this issue plagued me recently.
I've discovered that the case of the property calls in your mapping matters relative to paging. I.E. if you have a property with a column called "field" and you map it to another property as well, this will not be an issue if the case of field is the same.
However, if you identify your other mapping with a column called "Field", paging will not know that this is not a distinct property and will try to query the same column twice!
I guess that you have a CASE or duplicate problem.In my issue I have the following situation:
I take the column "serie id" two times but in different ways.. I put "S" in lower and in upper.. I hope that helps..
I've got the following problem. I built a PHP file, which reads categories from a file, to impor tthem into Magento. I am able to read the file, no problem. The connection via NuSOAP to the Magento API works aswell. I can get the SessionID and I am able to get data, like Information for a category, also its possible to delete categories.
But, whenever I try to create or update anything, it throws an error. The rights for the user are ok aswell. For example, when I create a category, I add the usual data to the call:
$proxy->call(
$sessionId,
'category.create',
$rootCategory, array(
'name' => "TEST",
'is_active' => '1',
'page_layout' => 'two_columns_right',
'description' => "TEST",
'meta_title' => "TEST",
'meta_description' => '',
'meta_keywords' => "TEST",
'include_in_menu' => '0',
'display_mode' => 'PRODUCTS',
'available_sort_by' => 'price',
'default_sort_by' => 'price',
'is_anchor' => '0'
)
);
All the time, it says:
(
[faultcode] => 102
[faultstring] => Category not exists. )
Which is not true. The $rootCategory is definatly a category, which is existing. I tried all other categories, I tried to add a 'path' to the info, I tried to use less information (only the neccesary stuff), I tried to read existing categories to get their IDs, NOTHING works. It always throws this faultcode.
Same happens, when I try to update a category, or create /update a product. Deleting is no problem at all.
Do you see the problem?
i just compared your NON working exemple and i found this while comparing it with another exemple i has ( i do not pretent to be expert ) ..
but seems like your $new_category, array(blahblha) ...
should be INSIDE an array according to the exemple i already have
like this array($new_category,array(blahblah) ...
this is the mains difference i just saw ..
here is the EXEMPLE i just pulled out of the web ... Adapt to your needs..
$proxy->call(
$sessionId,
'category.create',
array(
3,
array(
'name'=>'New openerp',
'is_active'=>1,
'include_in_menu'=>2,
'available_sort_by'=>'position',
'default_sort_by'=>'position')) );
Have you tried specifying the category_id key in your $rootCategory within the call:
$selectedCategory['category_id'],
array('name'=>'New Category Through Soap')
)
Reference: http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_category