I am attempting to query a MYSQL table with three 'scenarios' for finding objects. While I have successfully broken these into three separate queries I feel there has to be a 'better and faster' way to sift through the data. However, when I combine like below, I do not find any objects matching the query. This is using xPDO within MODx. The failed attempt is immediately below:
$orders=$modx->newQuery('Orders');
$orders->where(array(
array( //scenario #1
'Orders.start_date:<=' => $rentalDate->end_date,
'AND:Orders.start_date:>=' => $rentalDate->start_date
),
array( //scenario #2
'OR:Orders.end_date:<=' => $rentalDate->end_date,
'AND:Order.start_date:>=' => $rentalDate->start_date
),
array( //scenario #3
'OR:Orders.end_date:>=' => $rentalDate->start_date,
'AND:Orders.end_date:<=' => $rentalDate->end_date
)
));
$conflictingOrders = $modx->getCollection('Orders',$orders);
However, if I run each scenario separately, it does pick up the objects correctly. Example:
$s1Query=$modx->newQuery('Orders');
$s1Query->where(array(array('Orders.start_date:<=' => $rentalDate->end_date,'AND:Orders.start_date:>=' => $rentalDate->start_date)));
$s1Results=$modx->getCollection('Orders',$s1Query);
Any ideas where I am going wrong in the first code? Please let me know if any further information is needed. Cheers!
Helpful doc:http://rtfm.modx.com/xpdo/2.x/class-reference/xpdoquery/xpdoquery.where
The array scenarios in your code are being treated as AND conditions when listed in the $orders->where() method.
Try this:
$orders = $modx->newQuery('Orders');
$orders->where(array(
'Orders.start_date:<=' => $rentalDate->end_date,
'AND:Orders.start_date:>=' => $rentalDate->start_date
));
$orders->orCondition(array( //scenario #2
'Orders.end_date:<=' => $rentalDate->end_date,
'AND:Order.start_date:>=' => $rentalDate->start_date
));
$orders->orCondition(array( //scenario #3
'Orders.end_date:>=' => $rentalDate->start_date,
'AND:Orders.end_date:<=' => $rentalDate->end_date
));
// uncomment the following lines to see the raw query generated
// $orders->prepare();
// print_r($orders->toSql());
$conflictingOrders = $modx->getCollection('Orders',$orders);
Related
I have a tree node in my form. I am using kartik-v's Tree Manager.
This is my view code:
echo TreeViewInput::widget([
'query' => Tree::find()->addOrderBy('root, lft'),
'headingOptions' => ['label' => 'Set Permission'],
'name' => 'name',
'value' => '1,2,3',
'asDropdown' => false,
'multiple' => true,
'fontAwesome' => true,
'rootOptions' => [
'label' => '<i class="fa fa-tree"></i>',
'class' => 'text-success'
]);
But, in this I have to follow the same table structure as mentioned in the widget. I have some extra fields and more permissions. So it is a bit complicated to use the same structure.
Is it possible to pass the value in an array directly to this widget? If possible let me know the array format.
Now I am stuck with this tree node implementation.
You can do this by doing some tricks, or by using another way:
1) you can add a condition to your query like this:
Tree::find()->andWhere(['not in','id',[2,3,4]])->addOrderBy('root, lft'),
by this solution you can ignore unwanted rows like you send data direct in array...
2) you can use another solution by using js lib/plugin direct like jsTree, in this case you can create and pass custom array direct...look at this example: jsTree Example
I'm trying to create an AJAX form whereby the content of a select field populates based on the choice of a preceding select field (you see this a lot with 'country' populating 'state/province'). In my case, I want users to be able to choose their province only if active accounts exist in it.
The Javascript I can write no problem. Fetching the data is where I'm... not so much stuck as doing too much work. CakePHP likes to build select fields with options in an array of the form
$options = array(select_option_value => display_text)
My strategy, though functional, must be more convoluted than cake intended (this a is segment of a controller method).
$provinceData = $this->Account->find('all',array('recursive' => 0,
'joins' => array(
array(
'table' => 'provinces',
'type' => 'LEFT',
'conditions' => array('Account.province_id = provinces.id')
)),
'fields'=>array('provinces.id', 'provinces.name', 'provinces.abbrev'),
'conditions' => array('registration > 2')));
$provinces = array();
foreach($provinceData as $pd) {
/*note: lowercase, plural below b/c can't get 'alias' => 'Province'
to work in joins array above : ( */
$id = $pd['provinces']['id'];
$name = $pd['provinces']['name'];
$provinces[$id] = $name;
}
$this->set(compact('provinces'));
Can anyone point out a more appropriate way to do this? I assume there must be a MySQL query that can do this, but I'm pretty bad at writing elaborate MySQL queries in the first place, let alone via Cake's convention (and, for you MySQL gurus out there, I'm happy to do this from a Model->query(//MySQL code) call instead!
Any and all help truly appreciated.
Assuming the relationship Account belongsTo Province you can try this code:
$accounts = $this->Account->find(
'all',
array(
'fields' => array('Account.province_id', 'Province.name'),
'conditions' => array('Account.registration > 2'),
'group' => 'Account.province_id'
)
);
$provinces = Hash::combine($accounts, '{n}.Account.province_id', '{n}.Province.name');
$this->set(compact('provinces'));
edit: missed bracket and a period instead of an underscore . Now should work
Guys help me to do this. I'm new to YII. I want to display each item branches stock like this.
actual database
What is the best way to do this?
What you are looking for is a cross tab or pivot table. Here is a link: http://www.artfulsoftware.com/infotree/qrytip.php?id=523
I have been looking for the same thing and have a solution using CSqlDataProvider. It is important to note when using CSqlDataProvider it returns an array unlike CActiveDataProvider which returns an object.
Here is the model code
public function displayStock($id)
{
$sql='SELECT product_id, COUNT(*) as productCount FROM stock WHERE assigned_to = 2 GROUP BY product_id';
$dataProvider=new CSqlDataProvider($sql, array(
'pagination'=>array(
'pageSize'=>10,
),
));
return $dataProvider;
}
Here is the code for the veiw
$stockDataProvider = Stock::model()->displayStock(Yii::app()->user->id);
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'stock-grid',
'ajaxUpdate' => true,
'template'=>'{items}{summary}{pager}',
'dataProvider'=>$stockDataProvider,
'columns'=>array(
'product_id',
array(
'name'=>'test',
'value'=>'$data["productCount"]'
),
array(
'class' => 'CButtonColumn',
'template' => '{view} {update}',
),
),
));
When defining the SQL statement in the model, you can see we have set the COUNT(*) to be called productCount. Then in the view we reference that name in the columns array like so
array(
'name'=>'test',
'value'=>'$data["productCount"]'
),
So simply replace productCount with the name you have used.
I'm sure the above code could do with some tweaking ie using Binded params in the query etc, but this has worked for me.
Any comments or improvements are very welcome. I'm only about 8 months into php and 3 months into yii.
In my CakePHP site, I want to make a drop-down list of all Venues, and any Restaurants that have is_venue=1.
I've tried this in my events_controller:
$venueOptions = array(
'fields' => array('id', 'name_address'),
'order' => array('name'),
'join' => array(
array(
'table' => 'restaurants',
'alias' => 'Restaurants',
'type' => 'inner',
'fields' => array('id', 'name'),
'foreignKey' => false,
'conditions' => array('restaurants.is_venue = 1')
)
),
);
$venues = $this->Event->Venue->find('list', $venueOptions);
But it appears to still just be getting the venues. I don't really need an association between the two, since their associations will both be with an event, not each other.
Where have I gone wrong? Am I close, but just need to tweak this code, or am I just all-together doing it wrong?
I think you could do something along the lines of:
<?php
....
$v = $this->Venue->find( 'list' );
$r = $this->Restaurant->find( 'list' );
$venues = Set::merge( $v, $r );
natcasesort( $venues );
// print_r( $venues );
$this->set( 'venues', $venues );
...
?>
Which is quite like the code above - I just use the Set class and make sure to Controller::set the variable to the view.
Also added some basic sorting to show you one option even though array sorting has nothing really specific to do with CakePHP.
Also fixed some bad variable names where I had originally used $venues, and $restaurants - changed to be consistently $v and $r.
Join will not work if there's no relation between. Venue and Restaurant. You should call them separately and merge the results
$venues = $this->Event->Venue->find('list', $venueOptions);
$restaurants = $this->Event->Restaurant->find('list', array('conditions' => array('is_venue' => '1')));
$results = array_merge($venues, $restaurants);
// sort results
asort($results);
How do you use cakephp to count, for example the number of posts, made every month in a year?
Preferably using Model->find('count') and get the data in an array.
I just did something similar, using only CakePHP (no direct queries). It works in CakePHP 2, haven't tested in 1.x.
The code for your example would be something like this:
$params = array(
'recursive' => -1,
'fields' => array('id', 'MONTH(created)')
'group' => array('YEAR(created)', 'MONTH(created)')
);
$numberOfPosts = $this->Model->find('count', $params);
This comes close
Query
$data = $this->Post->query("SELECT COUNT(id),MONTH(created) FROM posts GROUP BY YEAR(created), MONTH(created);");
Return
Array
(
[0] => Array
(
[0] => Array
(
[COUNT(id)] => 1
[MONTH(created)] => 3
)
)
[1] => Array
(
[0] => Array
(
[COUNT(id)] => 2
[MONTH(created)] => 4
)
)
)
When using cake, I prefer to stay as close to the framework as possible. This means that I try to avoid writing queries directly in the controllers because this results in the model code being everywhere. Therefore I recommend one of two solutions
1: (and what I do with more complicated stuff): Create a view for the calculation that you want to do and create a model to match.
2: Use a query as mentioned before, but put it in the model class, not the application class.