I cant think up some good solution. My database structure is:
id name
----------
9 beer
10 beer {cold}
11 beer {hot}
12 juice
13 juice {orange}
14 juice {green}
15 juice {black}
I need select so possible output to have:
- one row of main product
- and all same products containing any text between characters {%} will be an alternatives of main product.
I need this output: (2 rows with alternatives -- but no 7 rows)
array(
array(
id => 9,
name => beer,
alternatives => array (
array(
id => 10,
name => cold
),
array(
id => 11,
name => hot
)
)
),
array(
id => 12,
name => juice
alternatives => array (
array(
id => 13,
name => orange
),
array(
id => 14,
name => green
),
array(
id => 15,
name => black
)
)
)
);
Do you think, is this possible with ONE Query?
Related
I have an array structured like so (this is the way the CSV formats it):
Array(
0 => Array(
0 => person1
1 => person2
2 => person3
//all the way to 9
),
1 => Array(
0 => id belonging to person 1
1 => id belonging to person 2
2 => id belonging to person 3
),
2 => Array(
0 => id belonging to person 1
1 => id belonging to person 2
2 => id belonging to person 3
),
//all the way to 20
)
I'm trying to sort a new array (of arrays), with each index being the value correspondent to the key in the 0 index above. i.e., person1 points to an array with all ids from the arrays 1-20 outside.
In each of the arrays after the index 0, it contains 20 ids, 0 belongs to the key 0 in the first array.
The structure I'm trying to achieve is shown below:
Array(
[person1] => Array(
id belonging to person 1
id belonging to person 1
id belonging to person 1
),
[person2] => Array(
id belonging to person 2
id belonging to person 2
id belonging to person 2
),
[person3] => Array(
id belonging to person 3
id belonging to person 3
id belonging to person 3
),
)
My attempt so far has worked, however, I had to hard code some of the indexes. What's the best solution to achieve the desired structure?
I'm a bit unsure if this is what you are looking for...
<?php
$arr = Array(
0 => Array(
0 => "person1",
1 => "person2",
2 => "person3"
//all the way to 9
),
1 => Array(
0 => "id belonging to person 1",
1 => "id belonging to person 2",
2 => "id belonging to person 3"
),
2 => Array(
0 => "id belonging to person 1",
1 => "id belonging to person 2",
2 => "id belonging to person 3"
)
);
foreach($arr[0] AS $id=>$name)
{
$ids[$id] = $name;
}
foreach(array_slice($arr,1) AS $persons)
{
foreach($persons AS $id=>$person)
{
// make sure to check if $ids[$id] exist and handle it as you like.
// if(isset($ids[$id]))
$people[$ids[$id]][] = $person;
}
}
print_r($people);
?>
result:
Array
(
[person1] => Array
(
[0] => id belonging to person 1
[1] => id belonging to person 1
)
[person2] => Array
(
[0] => id belonging to person 2
[1] => id belonging to person 2
)
[person3] => Array
(
[0] => id belonging to person 3
[1] => id belonging to person 3
)
)
EDIT: Should be noted I'm not making any checks on if the person's id exist in the $ids array, and neither if $people are ever set.
I'm using Cake 2.3.8 and having a bit of trouble searching for data efficiently. I'm retrieving the data I'm looking for, but also a lot of stuff I don't need due to containables.
For example Say I have the following tables
table reservations
id | confirmation_number | guest_id
1 123 1
2 345 2
table reservation_details -a reservation can have multiple entries (multiple rooms)
id | reservation_id | date | time | room_id | rate
2 1 2014-18-04 13:00 1 9.99
4 1 2014-18-04 14:00 2 4.99
5 2 2014-19-04 13:00 2 4.99
With the following models
//Reservation model
public $actsAs = array('Containable');
public $hasMany = array('ReservationDetail');
//ReservationDetail model
public $actsAs = array('Containable');
public $belongsTo = array('Reservation');
Now perform a search for reservations where the date is greater or equal to the 19th. The date is stored in the reservation_details table.
$reservations = $this->Reservation->find('all', array(
'conditions' => array(
'Reservation.guest_id' => '1'
),
'contain' => array(
'ReservationDetail' => array(
'conditions' => array(
'ReservationDetail.date >=' => '2014-19-04'
)
)
)
));
This search would return Reservation #1, an empty array for ReservationDetail for reservation #1. The issue is I don't want any of that information. I only want data to be returned if the ReservationDetail conditions matches my search. Right now, it's only returning an empty array for ReservationDetail if the match isn't found.
The result of the above search would be something like
Array(
[0] => array //I don't want this index to be returned at all because the reservation_details weren't met
(
[Reservation] => array
(
id => 1
confirmation_number => 123
guest_id => 1
)
[ReservationDetail] => array
(
)
)
[1] => array
(
[Reservation] => array
(
id => 2
confirmation_number => 345
guest_id => 2
)
[ReservationDetail] => array
(
id => 5
reservation_id => 2
date => 2014-19-04
time => 13:00
room_id => 2
rate => 4.99
)
)
)
As you can see, the ReservationDetail for the first result found did not meet my criteria. It still returns Reservation table and an empty array for ReservationDetail.
Is there some other way I can search so that the reservation table won't be returned at all if the ReservationDetail doesn't match my criteria?
$reservations = $this->Reservation->find('all', array(
'conditions' => array(
'Reservation.guest_id' => 1,
'ReservationDetail.date >=' => '2014-19-04'
),
'joins' => array(
array(
'table' => 'reservation_details',
'alias' => 'ReservationDetail',
'type' => 'inner',
'conditions' => array(
'ReservationDetail.reservation_id = Reservation.id'
)
)
),
'contain' => array(
'ReservationDetail'
)
));
I am trying to build a website that will display the text in multiple languages.
I have a table 'text' with all the languages. If the text does not exist in the chosen language it has to display the default language.
query SELECT * FROM text WHERE TextId = 10
results in
Id TextId LanguageId Text
10 10 1 first name
13 10 2 名前
If I r_print this result I get something like this
Array ( [0] => Array ( [0] => 10 [Id] => 10 [1] => 10 [TextId] => 10 [2] => 1 [LanguageId] => 1 [3] => first name [Text] => first name )
[1] => Array ( [0] => 13 [Id] => 13 [1] => 10 [TextId] => 10 [2] => 2 [LanguageId] => 2 [3] => 名前 [Text] => 名前 ) )
How can I check that LanguageId 2 exist in this array ?
the problem is that it is possible that TextId 2 and Id 2 can also exist in this array.
Is this possible to do with in_array()?
Here is a function that can check if LanguageId equals a special value .
function isLanguageIdExists($yourArray , $LanguageId){
$exists=false;
foreach($yourArray as $array){
if(isset($array['LanguageId'])&& $array['LanguageId'] == $LanguageId){
$exists=true;break;
}
}
return $exists;
}
$exist = isLanguageIdExists($yourArray , 2);//return true or false
You can check by isset the key and match the value in php.
$dataArray = array(
0 => array(0 => 10 ,'Id' => 10, 1 => 10, 'TextId' => 10, 2 => 1, 'LanguageId' => 1),1 => array(0 => 10 ,'Id' => 10, 1 => 10, 'TextId' => 10, 2 => 1, 'LanguageId' => 1)
);
foreach($dataArray as $value) {
if(isset($value['LanguageId']) && $value['LanguageId'] == 2) {
echo 'language ID 2 is available';
}
}
Working Demo
After giving this some more thought I came up with a maybe not so elegant solution.
Instead of getting an array back I modified the SQL Query to give one row back with the default language (English) and a user selected language (Japanese).
It uses two left joins. This shows that I received (some) training in SQL but am really not at ease with multidimensional arrays.
Query
def_text = text in default language
usr_text = text in user chosen language
$table01 = "text";
$query="SELECT $table01.TextId,
text_def.Text as def_text,
text_usr.Text as usr_text
FROM $table01
LEFT JOIN $table01 as text_def ON $table01.TextId = text_def.TextId AND text_def.LanguageId = $_SESSION[default_language]
LEFT JOIN $table01 as text_usr ON $table01.TextId = text_usr.TextId AND text_usr.LanguageId = $_SESSION[language]
WHERE $table01.TextId=$mess;";
after getting back the results it is easy to check with isset() or empty() to see if the text is available in the user selected language
I have two models, Component and Group. A Group has many Components, and a Component can be in many Groups. Now, what I need is a view, in which there's a table, n times m field (or matrix) of checkboxes. The Columns would be all the Groups (which would be fewer) and the rows would represent the Component. Basically, when the HaBTM-Relationship exists, the checkbox is checked.
This should be editable, meaning it would be wrapped in a form.
| Group 1 | Group 2 | Group 3
C1 | x | | x
C2 | x | x |
C3 | | | x
What is the least stressful way to achieve this in CakePHP?
Alright.
First of course you load the data from your connecting table. So you get a lot of datasets like:
id => 4
component_id => 4
group_id =>3
Then you have an array of all existing components and another one which contains all existing groups.
Since you have the components in rows I would reorganise this array of arrays, so that you have a multidimensional array which as first key has the component_id and under this id you have an array containing the arrays of all datasets, which contain this group.
e.g.:
array(
1 => array(
0 => array(
'id' => 4,
'component_id' => 1,
'group_id' => 2,
),
1 => array(
'id' => 4,
'component_id' => 1,
'group_id' => 5,
),
),
2 => array(
0 => array(
'id' => 4,
'component_id' => 2,
'group_id' => 1,
),
1 => array(
'id' => 4,
'component_id' => 2,
'group_id' => 3,
),
),
);
After this reorganisation you can pass it to the view, where you can iterate through it to build the form, giving each checkbox the component-group info, which you can collect after sending the form.
Nicer than that (as a version 1.2) would be a AJAX call which saves the combination immediately after activating or deactivating the checkbox. Your choice ;)
Calamity Jane
My database have category table that is related to more than one city. In the categories table the city column has comma separated id for example 1, 2, 3.
When I retrieve data from categories table i want that the city column contain the corresponding city names instead of city id.
$categoryDetails = $this->Category->find('first',array('conditions'=>array('slug'=> $slug)));
Array
(
[Category] => Array
(
[id] => 10
[parent_id] => 2
[city] => 2, 3, 4, 5, 6, 7, 8, 9, 10
[slug] => college
[type] =>
[lft] => 31
[rght] => 32
[name] => College
[description] => College
[image_name] => 1376938860_1185824_431052847008731_328184125_n.jpg
[created] => 1376938860
[modified] => 1376938860
)
)
CakePHP is designed to handle model relationships, what you're doing is completely circumventing what Cake has been designed to do. Furthermore, in general you do not want to link entries in separate tables by storing ids in a comma separated list. http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
If a city will only ever belong to one category, use a hasMany relationship. If a city can belong to many categories, use a HABTM relationship.
I'm guessing what you probably want is a HABTM relationship. Drop the city field from the categories table, and make an additional categories_cities table that has the fields category_id and city_id. For the example you gave, it should look like this:
category_id | city_id
10 | 2
10 | 3
10 | 4
10 | 5
10 | 6
10 | 7
10 | 8
10 | 9
10 | 10
Then add to your Category model the following:
public $hasAndBelongsToMany = array(
'City' =>
array(
'className' => 'City',
'joinTable' => 'categories_cities',
'foreignKey' => 'city_id',
'associationForeignKey' => 'category_id',
'unique' => true,
)
);
Once you've set up the relationship, Cake will naturally fetch the cities you've related to the category when you do a find for that category, assuming the model's recursive property is set to 0 or higher. (Defaultly, it's set to 1.) Alternatively, you can use the containable behavior.