Add condition to join table in pagination query (CakePHP 2.0.4) - php

I am new to cakephp. I have to do some improvements in the cakephp based application. In that, there are categories and images models. In the images table has lots of images. Default category images and other category related images details are maintaining in that table. It will display following queries in the 2nd page (pagination) of list categories.
SELECT `Category`.`id`, `Category`.`name`, `Category`.`slug`, `Category`.`meta_description`, `Category`.`meta_keywords`, `Category`.`sort`, `Category`.`color`, `Category`.`bgcolor`, `Category`.`modified`, `Category`.`created` FROM `categories` AS `Category` WHERE 1 = 1 ORDER BY `sort` ASC LIMIT 20, 20
SELECT `Image`.`id`, `Image`.`path`, `Image`.`size`, `Image`.`tags`, `Image`.`default`, `Image`.`category_id`, `Image`.`modified`, `Image`.`created` FROM `images` AS `Image` WHERE `Image`.`category_id` IN (60, 17, 9, 33, 71, 18, 73, 30, 58, 54, 3, 44, 64, 66, 67, 11, 53, 16, 23, 68)
But actually, the second query needs to be like:
SELECT `Image`.`id`, `Image`.`path`, `Image`.`size`, `Image`.`tags`, `Image`.`default`, `Image`.`category_id`, `Image`.`modified`, `Image`.`created` FROM `images` AS `Image` WHERE `Image`.`default` = 1 AND `Image`.`category_id` IN (60, 17, 9, 33, 71, 18, 73, 30, 58, 54, 3, 44, 64, 66, 67, 11, 53, 16, 23, 68)
There should be
Image.default = 1
in WHERE clause.
My CategoriesController.php index action is:
public function index() {
$this->Category->recursive = 1;
$this->Category->Behaviors->attach('Containable');
$this->paginate = array("contain"=>array("Image"));
$search="";
if(isset($this->params['named']['search'])){
$search = str_replace("%20"," ", $this->params['named']['search']);
$conditions = array(
'OR' => array(
array('Category.name LIKE' => '%'.$search.'%')
)
);
$this->set('categories', $this->paginate($conditions));
} else {
$this->set('categories', $this->paginate());
}
$success = $this-> Session->read('success');
$this->set(compact('search', 'success'));
}
And my Category model has :
public $hasMany = array(
'Panel' => array(...),
'Image' => array(
'className' => 'Image',
'foreignKey' => 'category_id',
'dependent' => false,
'conditions' => array('Image.default' => '1'),
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
So, I need to filter the join table images.default set to '1'

In your categories controller change this line:
$this->paginate = array("contain"=>array("Image"));
to:
$this->paginate = array("contain"=>array("Image.default = 1"));
More info here: http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html#containing-deeper-associations

Note: default recursive level is 1
Combine both condition into 1
$this->paginate = array("contain"=>array("Image.default = 1"),"recursive" => 1);
or make multiple conditions
$this->paginate = array('contain'=>array('Image'=>array('conditions'=>array('Image.default'=>1))))

Related

Laravel 5.2 - Delete duplicates from my query

i have a query like this:
$players = PostBalance::where('post_id', $post->id)->orderBy('id','desc')->get();
It work well and return array with all values, Post balances have fields:
ID
score
post_id
user_id
I would like Delete user_id duplicated AND get the max score value. for example if i have:
[0] = 'id' => 1 , 'score'=> 10, 'user_id'=> 1, 'post_id' => 1
[1] = 'id' => 2 , 'score'=> 20, 'user_id'=> 1, 'post_id' => 1
[2] = 'id' => 3 , 'score'=> 30, 'user_id'=> 1, 'post_id' => 1
[3] = 'id' => 4 , 'score'=> 40, 'user_id'=> 2, 'post_id' => 1
[4] = 'id' => 5 , 'score'=> 50, 'user_id'=> 2, 'post_id' => 1
[5] = 'id' => 6 , 'score'=> 60, 'user_id'=> 2, 'post_id' => 1
I would like delete duplicates user_id and get only the user_id with max score:
RESULT:
[0] = 'id' => 3 , 'score'=> 30, 'user_id'=> 1, 'post_id' => 1
[1] = 'id' => 6 , 'score'=> 60, 'user_id'=> 2, 'post_id' => 1
You can use groupBy() and max() method like this (note: this will not actually delete the duplicates from DB, but work for your query):
$result = PostBalance::groupBy('user_id')
->max('score');
For further reference, see Laravel Docs
Or if you want to order the results by score, you can do it like this:
$result = PostBalance::orderBy('score', 'desc')
->groupBy('user_id')
->get();
Note: To get max of group by, try to first run orderBy(), then run groupBy() on the query instead.
Hope this helps!

How to Traversal this?

I am working on an application that has a web based backend and a Android app based front end.
The backend is used to input data into MySQl (using PHP) and then generate a JSON which is then supplied to the Android App (front end) and displayed.
So here is what I have:
This is my Database
CREATE TABLE IF NOT EXISTS `tddept` (
`deptId` int(11) NOT NULL AUTO_INCREMENT,
`deptName` varchar(50) NOT NULL,
`deptIsRoot` tinyint(1) NOT NULL,
`deptHasChild` tinyint(1) NOT NULL,
`deptParentId` int(11) NOT NULL,
PRIMARY KEY (`deptId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=16 ;
--
-- Dumping data for table `tddept`
--
INSERT INTO `tddept` (`deptId`, `deptName`, `deptIsRoot`, `deptHasChild`, `deptParentId`) VALUES
(2, 'One', 1, 1, 0),
(3, 'Two', 1, 1, 0),
(4, 'Three', 1, 1, 0),
(5, 'One1', 0, 0, 2),
(6, 'One2', 0, 0, 2),
(7, 'One3', 0, 0, 2),
(12, 'Two1', 0, 0, 3),
(13, 'Three1', 0, 0, 4),
(14, 'Dept1', 1, 1, 0),
(15, 'dept1.1', 0, 0, 14);
My intention is simple to create a tree structure. only that there are multiple root nodes. and hence multiple leafs.
If put in simple words, I am trying to create a directory tree structure. I would want to display the data in the above table in to a dropdown menu (i.e. using <select> and <option>) as:
One
One1
One2
One3
Two
Two1
Three
Three1
Dept1
dept1.1
Where One, Two, Three, Dept1 are root departments while the rest are sub-departments.
There can definitely be situations in the future where in I might have to have something like:
- One
- - One1
- - - One1a
- - - One1b
so on and so forth.
How can I traversal through them using Core PHP and how can I display them in the very structure as above in to a <select>/<option> (dropdown) menu.
PS: any heads up on JSON would also be a great help.
Here's the solution for image2
echo '<select>';
structureTree(0,0);
echo '</select>';
function structureTree($deptParentId, $level){
$result = getDataFromDb($deptParentId); // change this into SQL
foreach($result as $result){
echo '<option value="'.$deptParentId.'">'.str_repeat('-',$level).$result['deptName'].'</option>';
structureTree($result['deptId'], $level+2);
}
}
// mocking database record
function getDataFromDb($deptParentId)
{
$data = array(
array(
'deptId' => 1,
'deptName' => 'IT',
'deptParentId' => 0,
),
array(
'deptId' => 2,
'deptName' => 'Human Resources',
'deptParentId' => 1,
),
array(
'deptId' => 3,
'deptName' => 'Opreational',
'deptParentId' => 1,
),
array(
'deptId' => 4,
'deptName' => 'Networking Department',
'deptParentId' => 1,
),
array(
'deptId' => 5,
'deptName' => 'Software Development',
'deptParentId' => 1,
),
array(
'deptId' => 6,
'deptName' => 'Mobile Software Development',
'deptParentId' => 5,
),
array(
'deptId' => 7,
'deptName' => 'ERP',
'deptParentId' => 5,
),
array(
'deptId' => 8,
'deptName' => 'Product Development',
'deptParentId' => 5,
),
);
$result = array();
foreach ($data as $record) {
if ($record['deptParentId'] === $deptParentId) {
$result[] = $record;
}
}
return $result;
}
regarding 1.png Here's the SQL based on your sample db table
SELEC dep.deptId As DepId
,dep.deptName As DepartmenName
,parent.deptId As ParentId
,parent.deptName As ParentDepartmentName
FROM tddept As dep
JOIN tddept As parent ON parent.deptParentId = dep.deptId;
recursion is the solution for this problem. While the parent still has a child then it keeps querying until there's no child left.
e.g
One
.One1
.One2
.One3
Here's the php application
function structureTree($depParentId = 0){
$result = queryFunction("SELECT *FROM
tddept WHERE deptParentId = '$depParentId'");
foreach($results as $result){
echo $result['deptName'].'<br/>';
structureTree($resultp['deptParentId']);
}
}
structureTree();

Trouble including array output in another array

I have the following code:
$tags = get_tags(array('exclude' => 46,5,101,22,122,7,102,15,104,47,105,66,43,123, 'fields' => ids));
$tagString = implode (',' , $tags);
echo $tagString;
Which echos out as...
10,121,20,36,23,66,24,21,105,76,82,17,22,122,43,47,102,5,6,106,8,75,54,38,57,86,56,101,123,95,25,62,16,39,40,69,37,9,42,7,15,41,87,73,85,104
This is great. However, I actually want to include the result (which I guess is $tagString) in another array as follows...
$args = array(
'post_type' => 'post',
'posts_per_page' => 12,
'paged' => $paged,
'tag__in' => array (46, 5, 101, 22, 122, 7, 102, 15, 104, 47, 105, 66, 43, 123),
'tag__not_in' => array ($tagString)
);
I've tried removing brackets adding single / double / no quotes, removing the word 'array' in front of $tagString across all combinations but it just doesn't work. When I manually create...
'tag__not_in' => array (10,121,20,36,23,24,21,76,82,17,6,106,8,75,54,38,57,86,56,95,25,62,16,39,40,69,37,9,42,41,87,73,85)
The code works perfectly. How can I get the output from $tagString to be the content of 'tag__not_in' array within the brackets? Is this possible?
========
Update to reflect Amal's code...
$tags = get_tags(array('exclude' => 46,5,101,22,122,7,102,15,104,47,105,66,43,123, 'fields' => ids));
$tagString = implode (',' , $tags);
echo $tagString;
$args = array(
'post_type' => 'post',
'posts_per_page' => 12,
'paged' => $paged,
'tag__in' => array (46, 5, 101, 22, 122, 7, 102, 15, 104, 47, 105, 66, 43, 123),
/*'tag__not_in' => array (10,121,20,36,23,24,21,76,82,17,6,106,8,75,54,38,57,86,56,95,25,62,16,39,40,69,37,9,42,41,87,73,85)*/
'tag__not_in' => explode(',', $tagString)
);
$tagString is a string - simply inserting it in array(...) won't create an array (unless you use eval(), which is generally a bad idea). Simply use explode() to create an array from the comma-separated string, like so:
'tag__not_in' => explode(',', $tagString)

how to add attributes to a category in magento with sql?

How can i add a attribute to a category in magento ?
I have read some tutorials and they said just insert two records but that doesn't work
Already changed a lot and playing with the values but still no result
After each change i have cleared the cache so that is nog the problem
I am working with magento 1.5 and flat tables
inserted the next querys and testing with the values
INSERT INTO `eav_attribute`
(
`attribute_id`,
`entity_type_id`,
`attribute_code`,
`attribute_model`,
`backend_model`,
`backend_type`,
`backend_table`,
`frontend_model`,
`frontend_input`,
`frontend_label`,
`frontend_class`,
`source_model`,
`is_required`,
`is_user_defined`,
`default_value`,
`is_unique`,
`note`
)
VALUES
(
158,
3,
'uitslag',
NULL,
'',
'varchar',
'',
'',
'text',
'Uitslag',
'',
'',
1,
0,
'',
0,
''
);
And
INSERT INTO `eav_entity_attribute`
(
`entity_attribute_id`,
`entity_type_id`,
`attribute_set_id`,
`attribute_group_id`,
`attribute_id`,
`sort_order`
)
VALUES
(
158,
3,
3,
3,
158,
61
);
Anyone a idea ?
Thanks in advance
Try something like this:
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttribute('category', 'uitslag', array(
'label' => 'Uitslag',
'type' => 'varchar',
'input' => 'text',
'visible' => true,
'required' => false,
'position' => 1,
));
The simply add values to categories either through the Magento admin, or directly into the catalog_category_entity_varchar table.

Pagination without default order

I have the code below:
$firm_ids = array(81, 96, 18, 5, 105);
$this->paginate = array(
'conditions' => array('Firm.id' => $firm_ids),
'limit' => 10,
);
$this->set('firms', $this->paginate('Firm'));
In the results I have the ordering in:
5, 18, 81, 95, 105
How do I disable the default order if I want to order as initial array ordering?
I found a workaround on some forum, see if this works:
$this->paginate = array(
'conditions' => array('Firm.id' => $firm_ids),
'limit' => 10,
'order' => array(
'FIELD(Firm.id,' . implode(',',$firm_ids) . ')'
)
);
what you need is order by field. here's the link.
Order By Field

Categories