What I have
In my OrdersTable.php:
$this->hasOne('Total', [
'className' => 'App\Model\Table\TotalsTable',
'foreignKey' => 'order_id',
'propertyName' => 'Total'
]);
Actual totals table:
| id | order_id | type | value |
|----|----------|----------|-------|
| 1 | 1 | total | 100 |
| 2 | 1 | tax | 20 |
| 3 | 1 | shipping | 5 |
The structure and logic come from opencart/opencart and I have no control over that.
What I want
This is a non-functional concept:
$query = $ordersTable->find('all', array(
'contain' => array(
'TotalTax' => [
'associationName' => 'Total',
'conditions' => function($query) {
return $query->where([
'TotalTax.type' => 'tax',
]);
},
],
'TotalShipping' => [
'associationName' => 'Total',
'conditions' => function($query) {
return $query->where([
'TotalShipping.type' => 'shipping',
]);
},
],
),
));
Do you guys think something like this is possible?
UPD: Creating an association for each type isn't an option since there may be too many of them
If this functionality is something that will be reused with your codebase, I would implement this logic at the table level and have two different conditional associations:
In OrdersTable.php
$this->hasOne('TotalTax', [
'className' => 'Totals'
])
->setConditions(['TotalTax.type' => 'tax'])
->setDependent(true);
$this->hasOne('TotalShipping', [
'className' => 'Totals'
])
->setConditions(['TotalShipping.type' => 'shipping'])
->setDependent(true);
Then you can simply contain them in the query:
$query = $ordersTable->find()->contain(['TotalTax', 'TotalShipping'];
An example of this can be found in the CakePHP documentation
How can I filter data-set in 2 Tables where second table have more results 1:n.
In first table I can use orWhere and I am getting right data, but my another Table contain multiple results and if I use contain or matching I am getting only data from second Table.
So, I want to filter both tables and get matched data.
Here is my query:
First query to filter first table
$query
->where([
'OR' => [
'Orders.id' => $freeText,
'Orders.postal' => $freeText,
'Orders.address LIKE' => '%' . $freeText . '%',
'Orders.city LIKE' => '%' . $freeText . '%',
'Users.first_name' => $freeText,
'Users.last_name' => $freeText,
'ProjectAddresses.cost_centre' => $freeText,
'CONCAT(first_name, last_name) LIKE' => '%' . str_replace(' ', '', $freeText) . '%',
'CONCAT(first_name, last_name) LIKE' => '%' . $freeText . '%',
'Users.first_name IN ' => $splittedKeywords,
'Users.last_name IN ' => $splittedKeywords,
]
]);
Second query - try to filter data from second Table (but still need matched data from first table)
$query->contain('Items', function ($q) use ($freeText) {
return $q->where(['vessel_id' => $freeText]);
});
So problem is if I use second query he automatically take only data from second table and my goal is to get all filtered data (from first and second table).
I have 20+ data-sets like:
(int) 0 => [
'id' => (int) 1,
'uuid' => '5f34ecda-6bc6-46ed-b5cc-b2227029aed8',
'user_id' => (int) 319,
'status' => (int) 30,
'order_price' => (float) 341.04,
'address_id' => (int) 379,
'address' => 'XYZ',
'building_number' => '171',
'postal' => '111',
'city' => 'XYZ',
'country' => 'AT',
'project_address' => [
'id' => (int) 379,
'type' => 'project',
'group_id' => (int) 3,
'default' => false,
'corresponding_invoice_address' => null,
'short_name' => 'XYT',
'comment' => '',
],
'user' => [
'id' => (int) 319,
'uuid' => '675216eb-7110-44d2-82a7-f7f020e934a6',
'title' => 'Herr',
'first_name' => 'Test',
'last_name' => 'Test',
],
'item_groups' => [],
'items' => [
(int) 0 => [
'id' => (int) 26,
'uuid' => 'f4f629be-e25e-4432-8d97-6b2adcee9065',
'item_group_id' => null,
'type' => (int) 2,
'status' => (int) 30,
'vessel_id' => (int) 40001,
'features' => [],
],
(int) 1 => [
'id' => (int) 28,
'uuid' => 'f4f629be-e25e-4432-8d97-6b2adcee9065',
'item_group_id' => null,
'type' => (int) 2,
'status' => (int) 30,
'vessel_id' => (int) 40003,
'features' => [],
],
(int) 1 => [
'id' => (int) 29,
'uuid' => 'f4f629be-e25e-4432-8d97-6b2adcee9065',
'item_group_id' => null,
'type' => (int) 2,
'status' => (int) 30,
'vessel_id' => (int) 40003,
'features' => [],
],
]
],
SQL
SELECT *
FROM orders Orders
INNER JOIN users Users ON Users.id = (Orders.user_id)
LEFT JOIN addresses ProjectAddresses ON ProjectAddresses.id = (Orders.address_id)
WHERE (Orders.id = :c0
OR Orders.postal = :c1
OR Orders.address LIKE :c2
OR Orders.city LIKE :c3
OR Users.first_name = :c4
OR Users.last_name = :c5
OR ProjectAddresses.cost_centre = :c6
OR CONCAT(first_name, last_name) LIKE :c7
OR Users.first_name IN (:c8)
OR Users.last_name IN (:c9))
Parameter is c1 = 4001 || %40001% || %40001
#ndm The goal is If somebody send in $freeText == 40003 I have to get as result this object where vessel_id = 40003 and thats works, but if somebody send in $freeText == Test then I need again same result because first_name == Test 8see first query) and when in second wuery I am using matching/contain this results are removed because he only "fetch" rows that are matching/contain Items...
Basically I want to check 10+ columns with given $freeText variable and if it is matching I want that results in my data-set (from both tables)
If I understood you correctly, then you're looking for a left join filter, ie left join Items (additionally to containing it for retrieval), group by Orders primary key (to avoid duplicates), and then simply add the Items.vessel_id condition to the main queries WHERE clause in order to make it a OR condition too.
$query
->contain('Items')
->leftJoinWith('Items')
->where([
'OR' => [
'Orders.id' => $freeText,
// ...
'Items.vessel_id' => $freeText
]
])
->groupBy('Orders.id');
See also
Cookbook > Database Access & ORM > Query Builder > Filtering by Associated Data
Cookbook > Database Access & ORM > Query Builder > Using leftJoinWith
$array = array(
'name' => 'john',
'age' => '25',
'birthday' => '02-03-1988',
'gender' => 'male',
'telephone' => '98676878',
'location' => 'Australia'
);
$array_slice = array_slice($array, 0, 3);
foreach($array_slice as $key => $val) {
if($key !== 'age') {
echo $key.' => '.$val.'<br>';
}
}
Output:
name => john
birthday => 02-03-1988
How to display 3 values of array?
So, I want output to be like this:
name => john
birthday => 02-03-1988
gender => male
I am very beginner in programmer, thanks for help.
Update: new solution after exchanging some comments below
You must filter the array and get the result in a new array. Then you display the content of the second array.
To filter your original array, use either array_intersect_key or array_filter functions.
I want to create a Form with CakePHP's FormHelper having a count fields for multiple items. My form looks like this:
| name | count |
|------------------------+-------|
| Item #1 | 2 |
| Item #2 | 0 |
| Item #3 | 15 |
| Item #4 | 1 |
What I need is a Form that submits data having the following structure:
array(
'Order' => array(
'0' => array(
'id' => 1
'count' => 2
),
'1' => array(
'id' => 2
'count' => 0
),
'2' => array(
'id' => 3
'count' => 15
),
'3' => array(
'id' => 4
'count' => 1
)
)
)
What I tried is this (within my Order view and ONLY the inputs, no table or layout!):
<?php
echo $this->Form->create('Order');
foreach ($item as $value) {
echo $this->Form->input('count', array('type' => 'number', 'min' => '0');
}
echo $this->Form->end('Submit');
?>
What I get is an array formed like this:
array(
'Order' => array(
'count' => '1'
)
)
I'm have quite a problem while trying to make a list (for the admin section) of HABTM relations. Here's the deal:
permissions: id, name;
users: id, username;
permissions_users: permission_id, user_id
Permission HasAndBelongsToMany User
I want to make a listing like such:
User.id | User.username | Permission.id | Permission.name
1 | Jack | 1 | posts
1 | Jack | 2 | comments
2 | Mark | 1 | posts
3 | Kate | 3 | tags
Stuff like: $this->Permission->User->find('all'); (or the other way around) doesn't really work, because it will fetch many permissions for Jack, also the other way around it will fetch many users for the posts permission, thus making it impossible to list in the view.
What I want is to get a array like:
[0] = > array(
[User] => array([id] => 1 [username] => Jack)
[Permission] => array([id] => 1 [name] => posts)
)
[1] = > array(
[User] => array([id] => 1 [username] => Jack)
[Permission] => array([id] => 2 [name] => comments)
)
...
Any ideas?
I think you would need to use the foreach and loop through your result to reconstruct a new array like that.
$user = array('id' => '1', 'name' => 'Jack');
$data = array();
foreach($permission as $per) {
$data[] = array($user, $per['Permission'])
}