I need to compare DATE format from a DATETIME.
Prior ZF 2.3.5, the following code was working fine:
$select->where('DATE(arrival_date) <= DATE(NOW())');
$select->where('DATE(departure_date) >= DATE(NOW())');
$select->where('enable = true');
With ZF 2.4.2+ it does not work anymore and produce the following error:
Cannot inherit previously-inherited or override constant TYPE_IDENTIFIER from interface Zend\Db\Sql\Predicate\PredicateInterface
I have tried the following (without error). The problem is that "arrival_date" is a DATETIME format, and I need to compare with a DATE only.
$where = new Zend\Db\Sql\Where();
$where->lessThanOrEqualTo('arrival_date', date('Y-m-d'));
$where->greaterThanOrEqualTo('arrival_date', date('Y-m-d'));
$where->equalTo('enable', true);
$select->where($where);
Ideally, this code should work, but it does not:
$select->where(new Zend\Db\Sql\Predicate\Expression('DATE(arrival_time) <= ?', 'DATE(NOW())'));
I am lost, any idea ?
Just use Expression like this:
$select->where(
array(
new \Zend\Db\Sql\Predicate\Expression("DATE(arrival_date) <= DATE(NOW())")
)
);
No need of ? like you tried. With ? you params will be escaped and it won't work with an expression. Only with params, like a PHP datetime or something like this.
Tested with 2.4.2
Related
I am currently trying to convert this JS code:
db.Issue.aggregate( [
{ // Filter out issues that have been worked on after our given week = All worklogs muste have been before date
$match : {
worklogs: { $all: [
{
"$elemMatch" : {
date: { $lte: endDate }
}
},
] }
}
}
] )
(Based on official documentation: Use $all with $elemMatch
Into Doctrine ODM code using their aggregation builder:
$builder = $this->createAggregationBuilder();
$aggregation = $builder
->match()
->field('worklogs')
->all([
$builder->matchExpr()->elemMatch(
$builder->expr()->field('date')->lte($week->getEndDate())
)
])
;
However, apparently I am unable to match the $all correctly - meaning in a way that allows me to ensure that all entries in a collection fulfilled the requirements checked by $elemMatch.
The original MongoDB query in JS seems to do the trick, but I cannot manage to receive the same results in PHP. By now I am not even sure Doctrine can handle that combination of $all and $elemMatch.
UPDATE:
Thank you all for your comments so far! I am however still struggling with the current query syntax (in PHP!) for the $not / ->not() operator. I have already checked the docs here: Doctrine ODM Docs but could not find anything useful. (Please also note, that I am using version 2.0 here).
Right now my query looks like:
->match()
->field('worklogs')
->not([
$builder->matchExpr()->elemMatch(
$builder->matchExpr()->field('date')->gt($week->getEndDate())
)
])
But leads to this error:
1) App\Tests\Repository\IssueRepositoryTest::testGetEstimationsPerWeek
MongoDB\Driver\Exception\CommandException: $not needs a regex or a document
/var/www/html/vendor/mongodb/mongodb/src/Operation/Aggregate.php:263
/var/www/html/vendor/mongodb/mongodb/src/Collection.php:223
/var/www/html/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php:168
/var/www/html/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Aggregation/Stage.php:35
/var/www/html/src/Repository/IssueRepository.php:85
So thanks to the help of #neil-lunn, I was able to figure out the correct query:
->match()
->field('worklogs')
->not(
$builder->matchExpr()->elemMatch(
$builder->matchExpr()->field('date')->gt($week->getEndDate())
)
)
This is function for search by datetime .. i want to search just by date ( yy-mm-dd ) what i need to search just with date withount datetime .
I have tried all the options, but no one makes what I need.
Thank you.
if it is Mysql then you can use DATE function
as something like this
$qb->AndWhere("DATE(m.startDate) = :start");
$qb->setParameter('start',date('Y-m-d'));
for Postgres like this
$qb->AndWhere("m.startDate::date = :start");
$qb->setParameter('start',date('Y-m-d'));
Doctrine have to be setup before https://simukti.net/blog/2012/04/05/how-to-select-year-month-day-in-doctrine2/
$emConfig = $this->getEntityManager()->getConfiguration();
$emConfig->addCustomDatetimeFunction('DATE', 'DoctrineExtensions\Query\Mysql\Date');
I'm using Yii to construct a web application. One of my input forms has a CJuiDatePicker for the date. I have two drop down lists, one for the hours, and one for the minutes.
My problem is in the data model, where I'm trying to convert the date, hour, and minute from the form into a MySQL datetime string. I have to produce a datetime string that looks like this - 2011-02-27 20:11:56, so Yii can convert the string into a MySQL datetime and insert the value into the row.
In the model, I have a rule that looks like this:
array('event_datetime_from', 'createDatetime',
'date'=>'event_date_from', 'hour'=>'event_hour_from',
'minute'=>'event_minute_from'),
The createDateTime validator function looks like this:
public function createDatetime($attribute, $params) {
if (!$this->hasErrors()) {
$date = $this->$params['date'];
$hour = $this->$params['hour'];
$minute = $this->$params['minute'];
if (trim($date) === '') {
$this->$attribute = null;
} else {
$parse = CDateTimeParser::parse(
$date.' '.$hour.':'.$minute,
'MM/dd/yyyy hh:mm');
$this->$attribute = date('Y-m-d H:i:s', $parse);
}
}
}
Now, I'm not a PHP developer. However, it appears to me that $params['date'] is returning the string value event_date_from, rather than the value of event_date_from.
My PHP question is, how do I get the value of event_date_from inside the createDateTime validator function?
My apologies if I overlooked the answer somewhere in the Yii documentation. I couldn't find many examples of validator functions. The Yii validator classes have a different parameter signature than validator functions.
Edited based on thaddeusmt's answer:
I tried extending CActiveRecord and coded an afterValidate method, but I couldn't find a place to define my working date, hour, and minute variables. I defined them in the extended method, and the afterValidate method couldn't see them. I got a PHP undefined variable error in the afterValidate method.
In the controller, I coded the following function:
protected function createDateTime($dateString, $hour, $minute) {
if (trim($dateString) == '') {
return null;
} else {
$timeString = $dateString.' '.$hour.':'.$minute;
return date('Y-m-d H:i:s', strtotime($timeString));
}
}
It should be a cinch to call a function in PHP, right?
I tried both of these calls in the actionCreate() function:
$model->event_datetime_from =
createDateTime($_POST['event_date_from'],
$_POST['event_hour_from'],
$_POST['event_minute_from']
);
and:
$model->event_datetime_from =
createDateTime($model->event_date_from,
$model->event_hour_from,
$model->event_minute_from
);
My controller code dies with either of these calls, and I get a blank (no HTML) response page.
I thought what I wanted to do was pretty simple. I want to take a date, hour, and minute string, and convert the concatenation to a datetime string. What am I missing?
What I do is, in the POST action in the Controller (where the POST vars are assigned), I convert the posted date and time values into a MySQL datetime with the date() and mktime() function, then validate/save. So, here is an example of the post action:
public function actionUpdate() {
$model=$this->loadModel();
if(isset($_POST['Model'])) {
$model->attributes = $_POST['Model']; // assign the rest of the POST vars here
$model->event_datetime_from = date(
'Y-m-d H:i:s', // convert the timestamp to the mySQL format
mktime( // create the timestamp from the posted date and time vars
$_POST['my-hour-var'], // set the hour
$_POST['my-minute-var'], // set the min
$_POST['my-second-var'], // set the sec
date("m"), // set the month
date("d"), // set the day
date("Y") // set the year
)
); // create a MySQL Y-m-d H:i:s format date from the POST vars
$model->save(); // this run the validation rules, naturally
}
}
(This assumes a model called "Model", POSTed hour, minute and second variables called my-hour-var, my-minute-var and my-second-var respectively, and that you are setting the DATE part to today.)
And here is an example of validation rule in the Model model using the CTypeValidator:
public function rules() {
return array(
array('event_datetime_from', 'type', 'type'=>'datetime', 'datetimeFormat'=>'yyyy-MM-dd hh:mm:ss', 'message' => '{attribute} is not a date and time!'),
}
I hope this helps!
I'd highly recommend checking out this extension:
http://www.yiiframework.com/extension/i18n-datetime-behavior/
It does some of this behavior automatically. You may need to update it a bit depending on how you expect your incoming dates to look. One way is to always run the property through strtotime() (built in php date parsing function) instead of the specific date parser in the extension.
I finally got my date, hour, and minute strings to convert to a datetime string.
Here's the code that I put in the actionCreate method and the actionUpdate method of the CalendarEventController:
$model->attributes=$_POST['CalendarEvent'];
// new code
$timeString = $_POST['CalendarEvent']['event_date_from'].' '.
$_POST['CalendarEvent']['event_hour_from'].':'.
$_POST['CalendarEvent']['event_minute_from'];
$model->event_datetime_from =
date('Y-m-d H:i:s', strtotime($timeString));
if (trim($_POST['CalendarEvent']['event_date_to']) === '') {
$model->event_datetime_to = null;
} else {
$timeString = $_POST['CalendarEvent']['event_date_to'].' '.
$_POST['CalendarEvent']['event_hour_to'].':'.
$_POST['CalendarEvent']['event_minute_to'];
$model->event_datetime_to =
date('Y-m-d H:i:s', strtotime($timeString));
}
I had two datetime fields in this model, with the second field optional. This code didn't work when I put it in a function. It only worked when I put the code inline in the two action methods.
I guess I don't understand PHP function calls. But, in case anyone else comes across this question, here's the answer that worked.
I have a weird problem using socialEngine DB class (based on zend framework).
I wrote something like this:
$statusTable = Engine_Api::_()->getDbtable('actions', 'activity');
$myPosts = $statusTable->fetchAll($statusTable->select()
->where('subject_id = ?',$id)
->where('comment_count > ?',0)
->where('type = ?',$type)
->where('date > ?',$newer_than)
->order('date DESC')
->limit(intval($num_items)));
Its a part of a plugin a made, the problem is the query generated is somthing like this:
SELECT `engine4_activity_actions`.*
FROM `engine4_activity_actions`
WHERE (subject_id = 5) AND (comment_count > 0) AND (type = ) AND (date > )
ORDER BY `date` DESC LIMIT 10
You can see that the $type and the $newer_than have disappeared, even though they have values ($type='status', $newer_than='01/01/2000')
EDIT:
It seems to respond only to integers and not strings, if i replace the 'status' with 0 it shows up in the query.
The server runs on php 5.3.2
There's a third optionnal argument on the where() method which is the type of your argument. Depending on your DB adapter it can maybe get an important thing to tell for the Zend_Db_Select query builder.
So you could try
->where('subject_id=?',$subject,'TEXT')
ZF API indicates as well "Note that it is more correct to use named bindings in your queries for values other than strings", this can help the query builder, to get the real type of your args, so you could try as well this way:
$myPosts = $statusTable->fetchAll($statusTable->select()
->where('subject_id=:psubject')
(...)
,array('psubject'=>$subject));
I'd like to return the customers from Magento who where created the day before OR who where updated the day before. I tried to play with addFieldToFilter, without any success.
I also tried to manipulate Zend_Db_Select, no success.
So now I'm stuck!
Here are some of my tries :
$customer = Mage::getModel('customer/customer');
$customers = $customer
->getCollection()
->getSelect()
->where("updated_at >= ? AND updated_at <= ?",$this->getFrom(), $this->getTo())
->orWhere("e.created_at >= ? AND e.created_at <= ?", $this->getFrom(), $this->getTo());
Or
->addFieldToFilter(
array(
array('attribute'=>'updated_at', 'gteq'=>$this->getFrom()),
array('attribute'=>'created_at', 'gteq'=>$this->getFrom())
),
'',
'left'
);
Thanks
I'd recommend against directly manipulating the select unless it's absolutely necessary and you know exactly what's going on behind the scenes in your version of Magento.
The following syntax should handle the tricky parts for you
$c = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToFilter(array(
array('attribute'=>'updated_at','from'=>'2010-05-12','to'=>'2010-05-30'),
array('attribute'=>'created_at','from'=>'2010-05-12','to'=>'2010-05-13')
));
var_dump( (string) $c->getSelect());
var_dump(count($c));
all you'll need to do is drop in the date ranges you want.
It is enough to use updated_at as your filter attribute, because it is set to current datetime when a user is created. So by filtering with this field you will get both new users and those who are not new but were updated in the given period. Here's the code to look for users updated or created during the last 24 hours:
$customers = Mage::getModel('customer/customer')->getCollection();
$customers->addAttributeToFilter('updated_at', array('gt' => date("Y-m-d H:i:s", time()-60*60*24)));
foreach($customers as $customer) {
//do sth
}
Thanks to Alan and Silvo, here is what I wrote :
->addAttributeToFilter(array(
array('attribute'=>'updated_at','from'=>$this->getFrom(),'to'=>$this->getTo())
));
Both answers were usefull. Thank you!