Yii - find all by composite key - php

How do I find all by primary key? I don't want to specify the start and end dates as they aren't relevant when opening within booking form
$bookingRoom = BookingRoom::model()->findByPk(array('roomId' => 1, 'bookingId' => 1, 'startDate' => '20140619', 'endDate' => '20140620'));

You should use the findAllByAttributes() option:
$bookingRoom = BookingRoom::model()->findAllByAttributes(array('roomId' => 1, 'bookingId' => 1, 'startDate' => '20140619', 'endDate' => '20140620'));
If you don't want the startDate and endDate included remove it from the array.
Here is the documentation:
http://www.yiiframework.com/doc/api/1.1/CActiveRecord#findAllByAttributes-detail

you can try this:
$id = // code to set the id
$bookingRoom = BookingRoom::model()->findAllByPk($id);

Related

PHP count how many times a week certain operation occured

I have this array data structure:
$records = [];
$records[] = ['id' => 1, 'date' => '2017-03-12', 'operation' => 'sent_email'];
$records[] = ['id' => 1, 'date' => '2017-03-13', 'operation' => 'sent_email'];
$records[] = ['id' => 1, 'date' => '2017-03-13', 'operation' => 'sent_email'];
$records[] = ['id' => 1, 'date' => '2017-03-14', 'operation' => 'forgot_password'];
$records[] = ['id' => 1, 'date' => '2017-03-14', 'operation' => 'sent_email'];
$records[] = ['id' => 2, 'date' => '2017-03-14', 'operation' => 'sent_email'];
$records[] = ['id' => 2, 'date' => '2017-03-14', 'operation' => 'forgot_password'];
$records[] = ['id' => 1, 'date' => '2017-03-27', 'operation' => 'sent_email'];
$records[] = ['id' => 1, 'date' => '2017-03-29', 'operation' => 'sent_email'];
In this array I store operations that were done by website visitors. Obviously visitor can be identified by an id number.
What I want to do is to count how many times in a week (between Monday and Sunday inclusively) each visitor used 'sent_email' operation.
For example: first record with 'sent_email' operation shows that this operation happened in '2017-03-12' (Sunday), so that means this operation took place just once in that week for user with an id = 1.
Other next three 'sent_email' operations for user with an id = 1 happened three times in another week. (2017-03-13, 2017-03-13, 2017-03-14 those three dates belong to the same week).
I know that I probably need to loop through each record and somehow to check those dates if they belong to the same week, but I feel confused and stuck here, I don't understand logical steps needed to accomplish it. I would be really grateful if anyone could give me an explanation or pseudo code, whatever it is that would help me to tackle this problem, I really enjoy solving problems myself but because I'm stuck, I just need someone to get me up and running.
Thank you in advance for any help you can provide.
The DateTime object and the strtotime() functions both understand relative date strings, so you can do neat things like "last tuesday" and "3 days ago".
Some pseudo-code to get you started:
// figure out when your monday is
monday = ...
// figure out when your sunday is
sunday = ...
// loop over all records
foreach $record:
// skip records outside the date range you want
if date < monday or date > sunday then skip this record;
// skip records not of the type you want
if operation != email then skip this record;
// register a hit for this user
increment counter for user

Return a 4-dimension array with SQL and Codeigniter

I need to do a query and get certain kind of data. I have 2 tables, users and connections, I need to get per user how many times he/she connected per month and year.
users connections
........... ................
john 10/02/2014
john 15/02/2014
john 03/01/2015
john 06/02/2015
Is there a chance to get this info in this format:
john=>
[0]=>2014
[0]=>02
'total' =>2
[1]=>2015
[0]=>01
'total' => 1
[1]=>02
'total' => 2
[2]=>03
'total'=> 1
I'm using Codeigniter and also PHP.
Answering to #CodeGodie what I've done so far is:
public function getPeriodicity(){
$this->db->select('u.vusr_user, extract (MONTH from (to_timestamp(c.vuc_log_in))) as month, extract (YEAR from (to_timestamp(c.vuc_log_in))) as yearly, COUNT(c.vuc_log_in)');
$this->db->from('vts_users_conn c');
$this->db->join('vts_users u', 'c.vuc_vusr_id = u.vusr_id');
$this->db->group_by('u.vusr_user, month, yearly','asc');
$query = $this->db->get();
return $query->result_array();
}
Assuming you are using Codeigniter's $this->db->result_array() to obtain your database results, your initial array will look like this:
$res = array(
array(
"name" => "john",
"date" => "10/02/2014"
),
array(
"name" => "john",
"date" => "15/02/2014"
),
array(
"name" => "john",
"date" => "03/01/2015"
),
array(
"name" => "john",
"date" => "06/02/2015"
),
array(
"name" => "john",
"date" => "06/03/2015"
)
);
In order to change this array to your desired output, I would do the following:
foreach ($res as $row) {
$date_arr = explode("/", $row['date']);
$n = $row['name'];
$y = $date_arr[2];
$m = $date_arr[1];
if (!isset($final[$n]))
$final[$n] = array();
if (!isset($final[$n][$y]))
$final[$n][$y] = array();
if (!isset($final[$n][$y][$m])) {
$final[$n][$y][$m] = array("total" => 1);
} else {
$final[$n][$y][$m]["total"] = $final[$n][$y][$m]["total"] + 1;
}
}
If you var_dump your final result (var_dump($final)), you will get the following:
array (size=1)
'john' =>
array (size=2)
2014 =>
array (size=1)
'02' =>
array (size=1)
'total' => int 2
2015 =>
array (size=3)
'01' =>
array (size=1)
'total' => int 1
'02' =>
array (size=1)
'total' => int 1
'03' =>
array (size=1)
'total' => int 1
Hope this helps.
As a general rule, if you can access the data and see in your mind how you want that data to look, then it's pretty much possible to get it to do that. It's just a matter of working out the process.
In your case, I would do the following steps:
Order the data by users, then by date so everything is nicely together
Loop through the data and each time, check that the current user is the same as the last one. if it's not, create a new array key
split the date into the parts you want
check the user array for the key relating to year for that user. If the year exists, search for the month. If the month exists, add 1 to the total for that month. If the year and/or month don't exist, create the keys and set the total to be 1 for that month
Once the records have been processed, you should have the data in the format you need.

MONGO DB - PHP. Query in multiple nested data field

here expample of my data:
'_id' => new MongoId("54087e076c03943c3c8b456b"),
'fornitureFuture' =>
array (
'0' =>
array (
'data_start'▼ => new MongoDate(1412114400, 0),
'data_end' => new MongoDate(1414710000, 0),
'f1' => '65',
'f2' => new MongoInt32(0),
'f3' => '45',
'fornitore' => new MongoId("5346cb2ab9d6f0021e6b18a0"),
),
'1' =>
array (
'data_start' => new MongoDate(1420066800, 0),
'data_end' => new MongoDate(1427752800, 0),
'f1' => '63.75',
'f2' => new MongoInt32(0),
'f3' => '70.4',
'fornitore' => new MongoId("533406896c0394a62c8b4569"),
),
i need to find if exist a data in fornitureFuture with my MongoDate between data_start and data_end ...
first group data_start is 10/01/2014 and data_end 10/31/2014
Second group data_start is 01/01/2015 and data_end 03/31/2015
Something like:
//today is 09/19/2014
$dataTest = mktime(0,0,0,date('n')+2,14,date('Y')); //return 11/14/2014
$testMese = $this->db->getOne('MyCollection', array('_id'=> new \MongoId($thisPodPdr['_id']), 'fornitureFuture.data_start'=>array('$lte'=> new \MongoDate($dataTest)) , 'fornitureFuture.data_end'=>array('$gt'=> new \MongoDate($dataTest)) ) , array('fornitureFuture'=>1) );
I expect empty response but return the record..
2 example:
$dataTest = mktime(0,0,0,date('n')+7,14,date('Y')); //return 04/14/2015
$testMese = $this->db->getOne('MyCollection', array('_id'=> new \MongoId($thisPodPdr['_id']), 'fornitureFuture.data_start'=>array('$lte'=> new \MongoDate($dataTest)) , 'fornitureFuture.data_end'=>array('$gt'=> new \MongoDate($dataTest)) ) , array('fornitureFuture'=>1) );
return correctly empty!
I need to test in the same block ...something like
'fornitureFuture.$.data_start'=>array('$lte'=> new \MongoDate($dataTest)) , 'fornitureFuture.$.data_end'=>array('$gt'=> new \MongoDate($dataTest))
but dont work .
the \ is from namespace and this->db->getOne(collection,$query,$fields) is my function like $this->collection->findOne($query,$fields);
No syntax error.
sorry for my english and thanks for the help
Your first example, which returns 2 results when you expect none, runs the following query:
[
'_id' => new MongoId(...),
'fornitureFuture.data_start' => ['$lte' => new MongoDate(1418533200)],
'fornitureFuture.data_end' => ['$gt' => new MongoDate(1418533200)],
]
The example document you provided has two array elements, with the following date ranges:
1412114400 to 1414710000
1420066800 to 1427752800
This document matches because 1412114400 (of the first element) is less than 1418533200, and 1427752800 (of the second element) is greater than 1418533200. By simply referring to fornitureFuture.data_start and fornitureFuture.data_end, MongoDB's query matcher will be satisfied if any array element's sub-field meets the criteria.
You likely want to restrict start/end criteria to same array element, in which case $elemMatch is what you're looking for:
[
'_id' => new MongoId(...),
'fornitureFuture' => [
'$elemMatch' => [
'data_start' => ['$lte' => new MongoDate(1418533200)],
'data_end' => ['$gt' => new MongoDate(1418533200)],
],
],
]
This criteria should now match only when the start/end dates of the same element satisfy the range. On a related note, you may also be interested in the $ projection operator, to limit fornitureFuture to only the matched element(s).

$addToSet and $inc for updating a row

I'm working on a rating system. When a user rates, $inc increments the field, and addToSet adds the user_id to make sure the user only clicks rate once. I am checking if the user_id is already in the x field before updating, but that is another query which I'd rather avoid. Can I reach this purpose without having to write another query? I mean, $addToSet only adds if there is no value like that; can I instead get affected rows? Can you suggest other queries?
Thank you!
..->update(
array("_id" => $idob),
array(
'$inc' => array($type => (int) 1),
'$addToSet' => array("x" => (int) $user_id)
)
);
Ok I see the problem.
..->update(
array("_id" => $idob),
array(
'$inc' => array($type => (int) 1),
'$addToSet' => array("x" => (int) $user_id)
)
);
The problem is that you need a conditional $inc there so that it only $incs if it does add to set.
This is not possible with a unique index since unique indexes work from the root of the document atm. Also you probably want to use the $inc as a form of pre-aggregation or what not.
One method could be:
update(
array('_id' => $idob, 'x' => array('$nin' => array($user_id))),
array(
'$inc' => array($type => 1),
'$push' => array('x' => (int)$user_id)
)
)
This will only do the update if that user_id does not already exist in x.

Insert Date into database table using Zend framework insert method

I have the foll code as:
$table_project_win = new Application_Model_DbTable_AfterWinProject();
$data_win = array(
'project_id' => $project_id,
'project_name' => $project,
'project_type_id' => $pro_type,
'start_date' => $dateStart,
'end_date' => $dateEnd,
'project_size' => $size,
'project_description' => $pro_des
);
$table_project_win->insert($data_win);
Here I get the $dateStart and $dateEnd variabled using as:
$dateStartt = $this->_getParam('dateStart');
echo 'date Start: '.$dateStartt;
$dateStart='"'.$dateStartt.'"';
$dateEndd = $this->_getParam('dateEnd');
$dateEnd='"'.$dateEndd.'"'
By using getParam I get the value of the date that the user has given input But when i will insert it into the database I use as
$dateStart='"'.$dateStartt.'"';
$dateEnd='"'.$dateEndd.'"'
But in the database table the value for date inserted is '0000-00-00' While when I echo the $dateStart which I have got through getParam It gives the correct value as '2012-12-11'.What is the reason of it??What Should I do??
replace $dateStart='"'.$dateStartt.'"';
with
$dateStart= $dateStartt ;
or
$dateStart='`'.$dateStartt.'`';

Categories