CakePHP containable searches - php

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'
)
));

Related

insert multiple records at once for single foreign key

based on insert multiple rows using one forigenk value in form
according to above picture there is dropdown for select project.once select project and user will be able to add other details. now i want to do when form is submitting project_id (id map with project name in drop down)should insert with other rows.
but in my case project_id is inserting with only very first row. below result came when i print the array .
Array ( [0] => Array ( [project_id] => 1 [staff_id] => 2 [item_no] =>
1 [description] => 1 [qty] => 1 [unit] => cube [rate] => 1
[laboure_hrs] => 1 [laboure_cost] => 1 [amount] => 2 ) 1 => Array (
[project_id] => [staff_id] => 2 [item_no] => 2 [description] => 2
[qty] => 2 [unit] => sq.ft [rate] => 2 [laboure_hrs] => 2
[laboure_cost] => 2 [amount] => 8 ) [2] => Array ( [project_id] =>
[staff_id] => 2 [item_no] => 3 [description] => 3 [qty] => 3 [unit] =>
cube [rate] => 3 [laboure_hrs] => 3 [laboure_cost] => 3 [amount] => 18
) )
how i can pass project_id for another fields. my code is below
controler
public function create(){
// validate fields
$this->form_validation->set_rules('work_product_id', 'Work Product Id', 'required');
$this->form_validation->set_rules('work_item_description', 'Work Item Description', 'required');
$this->form_validation->set_rules('quantity', 'Quantity', 'required');
$this->form_validation->set_rules('rate', 'Rate', 'required|numeric');
$this->form_validation->set_rules('laboure_hrs', 'Laboure Hrs', 'required|numeric');
$this->form_validation->set_rules('laboure_cost', 'Laboure Cost', 'required|numeric');
if ($_POST)
{
$project_id=$this->input->post('project');
$staff_id=$this->input->post('staff_id');
$item_no=$this->input->post('work_product_id');
$description=$this->input->post('work_item_description');
$qty=$this->input->post('quantity');
$unit=$this->input->post('unit');
$rate=$this->input->post('rate');
$laboure_hrs=$this->input->post('laboure_hrs');
$laboure_cost=$this->input->post('laboure_cost');
$amount=$this->input->post('txtmultTotal');
$data= [];
for ($i = 0; $i < count($this->input->post('work_product_id')); $i++)
{
$data[$i] = array(
'project_id' => $project_id
'staff_id' => $staff_id[$i],
'item_no' => $item_no[$i],
'description' => $description[$i],
'qty' => $qty[$i],
'unit' => $unit[$i],
'rate' => $rate[$i],
'laboure_hrs' => $laboure_hrs[$i],
'laboure_cost' => $laboure_cost[$i],
'amount' => $amount[$i],
);
}
print_r($data);
$this->boq_model->create($data);
}
}
model
function create($data){
$this->db->insert_batch('boq',$data);
}
I think you want to insert a single row into your project table, and then insert several rows into your item table using the value of your project_id column as a foreign key.
(With respect, your question is hard to understand; you may get a better answer than mine if you get help editing it from someone with good English-language skills.)
Here's what you do.
First, INSERT a row into your project table. Do not mention the project_id column in your INSERT query, so MySQL will assign an autoincrementing primary key.
INSERT INTO project (name, whatever) VALUES (?, ?);
Then, retrieve the value of the autoincrementing ID using LAST_INSERT_ID() as follows.
SET #project_id := LAST_INSERT_ID();
Then, insert rows into your item table using that value.
INSERT INTO item (project_id, description, qty, whatever)
VALUES (#project_id, ?, ?, ?)
The trick is to retrieve the value of LAST_INSERT_ID() right after your master-table insertion and store it in the MySQL user-defined variable #project_id. Then you use it for each insertion into your detail table.
From your html, the project_id is not a control array. So what you should do is to retrieve the project_id before the loop and use it in the loop or remove the [$i] in front of the project_id in the loop

mysql pattern select based on values

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?

PHP array sort mutli-dimensional

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.

check if a value exist in array from database query

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

Sort multidimensional array (PHP) - date complications and counting

I have the following output of an array using PHP. I need to do two things... First, I need to sort the array so it prints by the most recent date. I can't use a simple sort, because the date is outputted in the format mm/dd/yyyy (and not a regular time stamp) ...
Then I need to count how many rows exist for each year.
So, in the example below, I would need to know that there are ...
2 entries from 2010
2 entries from 2011
1 entry from 2012
Stop counting when there are no more rows
Since the year is not separate from the rest of the date digits, this also complicates things...
Array
(
[0] => Array
(
[racer_date] => 11/15/2010
[racer_race] => Test Row 4
[racer_event] => 321
[racer_time] => 16
[racer_place] => 12
[racer_medal] => 1
)
[1] => Array
(
[racer_date] => 7/15/2010
[racer_race] => Test Row 3
[racer_event] => 123
[racer_time] => 14
[racer_place] => 6
[racer_medal] => 0
)
[2] => Array
(
[racer_date] => 7/28/2011
[racer_race] => Test Row
[racer_event] => 123
[racer_time] => 10
[racer_place] => 2
[racer_medal] => 2
)
[3] => Array
(
[racer_date] => 10/9/2011
[racer_race] => Test Row 2
[racer_event] => 321
[racer_time] => 12
[racer_place] => 3
[racer_medal] => 3
)
[4] => Array
(
[racer_date] => 10/3/2012
[racer_race] => World Indoor Championships (final)
[racer_event] => 400m
[racer_time] => 50.79
[racer_place] => 1
[racer_medal] => 1
)
)
function cmp($a, $b)
{
if (strtotime($a["racer_date"]) == strtotime($b["racer_date"])) {
return 0;
}
return (strtotime($a["racer_date"]) < strtotime($b["racer_date"])) ? -1 : 1;
}
usort($array, "cmp");
call your array $array, and above code will sort it..
And to count entities you'll need to run foreach and check date('Y',strtotime($a["racer_date"])) in that foreach which will give you year in 4 digit..

Categories