I am currently working on a web application that will allow me to change the timezone during the execution. I started to test some cases, but it unfortunately doesn't work for the CGridView.
Working tests
This code here works for changing the timezone. I use the setTimeZone() function wich is a wrapper of the date_default_timezone_set() function.
Yii::app()->setTimeZone("America/Montreal");
echo "mtl:".date("Y-m-d H:i", 1396624849)."<br>";
Yii::app()->setTimeZone("Asia/Gaza");
echo "gz:".date("Y-m-d H:i", 1396624849);
The output is making a lot of sens (mtl:2014-04-04 11:20, gz:2014-04-04 18:20).
CGridView implementation
When I try the exact same line in a view with a CGridView, it doesn't work and displays only my default date format. Here is the code:
Yii::app()->setTimeZone("Asia/Gaza");
echo Yii::app()->getTimeZone();
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'reports-grid',
'dataProvider'=>$dataProvider,
'filter'=>$filtersForm,
'columns'=>array(
array(
'header'=>'Date',
'name'=>'inserted',
'type'=>'raw',
'value'=>'date(Yii::app()->params->dateformat, strtotime($data->inserted));'
),
),
));
The output date stays the same even if I change the time zone for America/Montreal.
What was tried so far
Adding the setTimeZone() function to a function with the date definition, as so:
'value'=>function($data){
Yii::app()->setTimeZone("America/Montreal");
return date(Yii::app()->params->dateformat, strtotime($data->inserted));
}
The result was the same as before.
Conclusion
Why is it not working? Is there a way to change the timezone dynamically in Yii? Is it possible that it doesn't work because the CGridView is built with eval operations?
Try this, it should work.
$dateTime = new DateTime();
$dateTime->setTimezone(new DateTimeZone('Asia/Gaza'));
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'reports-grid',
'dataProvider'=>$dataProvider,
'filter'=>$filtersForm,
'columns'=>array(
array(
'header'=>'Date',
'name'=>'inserted',
'type'=>'raw',
'value'=>function($data) use ($dateTime){
$dateTime->setTimestamp(strtotime($data->inserted));
return $dateTime->format(Yii::app()->params->dateformat);
}
))
));
By setting the timezone outsite of the function and using it inside, it should all work fine.
try this:
'value' => function($data){
Yii::app()->setTimeZone("Asia/Gaza");
return date(Yii::app()->params->dateformat, strtotime($data->inserted));
},
Related
Here's the code i want to work with
<?php echo $form->textField($model,'email_time_created',array('readonly'=>true)); ?>
i want to automatically add the current time to my database
I recommend it to add it at the database, asuming you're using MySQL you can create a trigger before saving and doing something like this:
SET NEW.email_time_created=NOW()
If not, you can do it at Yii/PHP level by adding the following function at the model class:
public function beforeSave(){
$this->email_time_created = CDbExpression('NOW()'); //Only in MYSQL
return parent::beforeSave();
}
It will set the column to the current value before saving the model. Notice that it won't be shown at the form, but you can add it by JS or using php's date() at the form's view.
also you can set the value in controller.
$model->email_time_created= now('Y-m-d H:i:s');
The simplest way is to add CTimestampBehavior to your model:
public function behaviors(){
return array(
'CTimestampBehavior' => array(
'class' => 'zii.behaviors.CTimestampBehavior',
'createAttribute' => 'create_time_attribute',
'updateAttribute' => 'update_time_attribute',
)
);
}
See API.
My issue is two-fold. First, I'm unable to correctly set the keyField for CArrayDataProvider, all I'm getting back is a string instead of a value. Second, I'm trying to use the keyField inside of CArrayDataProvider to set an id on the button in each row inside of CGridView. The reason I want to do this is so that I can pass the id value onward to an ajax function (if there's a better way to do this in Yii, I'm all ears). Any help would be much appreciated, thanks in advance!
I also posted this question once on Yii's forums. I normally wouldn't repost, but I have had a hard time getting answers there, as opposed to stack overflow, you guys are the best! Here's the link to my original post if anyone is interested.
Here is how I'm building the array that I'm using as my RAW data:
foreach ($items as $item) {
$tableRow = array("id"=>$item["Id"], "Organization"=>$item["Organization"], "Roles"=>$item["Roles"]);
$return_items[] = $tableRow;
}
Here is the CArrayDataProvider setup I'm using. I noticed that 'keyField' is not being given the id value, just the string 'id':
$dataProvider=new CArrayDataProvider($return_items, array(
'keyField'=>'id',
'sort'=>array(
'attributes'=>array(
'Organization',
'Roles',
),
),
'pagination'=>array(
'pageSize'=>10,
),
));
Lastly, here is the CGridView I'm trying to setup in the view. All that appears on the button is the id tag, but no value:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$authItems,
'columns'=>array(
'Organization',
'Roles',
array('name'=>'',
'type'=>'raw',
'htmlOptions'=>array('id'=>'id'),
'value'=>'CHtml::button("Edit Roles", array("data-toggle"=>"modal", "data-target"=>"#roles-modal"))'),
),
));
Try passing it via CHtml::button which you have already applied. E.g.
'value'=>'CHtml::button("Edit Roles", array(
"id"=>$data["id"],
"data-toggle"=>"modal",
"data-target"=>"#roles-modal"
))'),
I am using CJuiDatePicker in my form and I need to use two different formats: mm/dd/yy to be shown and dd/mm/yy to be sent in $_POST.
$questionario->widget('zii.widgets.jui.CJuiDatePicker', array(
'model' => $modeloDoQuestionario,
'attribute' => 'data_preenchimento',
'language' => 'en',
'options' => array(
'showAnim' => 'fold',
'showButtonPanel' => true,
'showOn' => 'both',
'dateFormat' => 'dd/mm/yy',
'altField' => '#Questionarios_data_preenchimento',
'altFormat' => 'mm/dd/yy',
),
'htmlOptions' => array(
'style' => 'height:14px;'
),
));
This is the field in HTML:
<input style="height:14px;" id="Questionarios_data_preenchimento" name="Questionarios[data_preenchimento]" type="text" />
But I still get the mm/dd/yy format in $_POST... What can be wrong?
You can put in the configuration file: 'main.php' something like this:
'widgetFactory' => array(
'widgets' => array(
'CJuiDatePicker' => array(
'scriptFile' => 'jquery-ui.min.js',
'language' => 'en',
'options' => array(
'dateFormat' => 'dd/mm/yy',
'showAnim' => 'fold',
'fontSize' => '0.85em',
),
),
),
),
With this ever that you call a 'CJuiDatePicker' widget will inherit this format.
I was looking for the same thing and have a slightly different solution.
I was mainly looking for on form pages to display the date as DD-MM-YYYY and save in the database as YYYY-MM-DD.
Regardless of changing the dateFormat option on CJuiDatePicker and even trying to use altFormat (using altField as well as apparently this is necessary) option, the date did not show in the desired format, granted if I were to change the date, the format would be shown correctly.
So I created a Custom class in components and created two methods, one to reformat the date to the DD-MM-YYYY format and one to format the date to the correct YYYY-MM-DD to be saved in the database.
Here is the Custom class (the file is called Custom.php and kept in components.)
class Custom
{
/*
**This method formats the date to be human readble ie 21-06-2013
*/
public function reformatDate($date)
{
if($date == '0000-00-00')
{
$newDate = '00-00-0000';
return $newDate;
}
elseif($date == '')
{
return $date;
}
else
{
$newDate = date("d-m-Y", strtotime($date));
return $newDate;
}
}
/*
**This method formats the date to the correct format according to the database
*/
public function formatDate($date)
{
if($date == '00-00-0000')
{
$newDate = '0000-00-00';
return $newDate;
}
elseif($date == '')
{
return $date;
}
else
{
$newDate = date("Y-m-d", strtotime($date));
return $newDate;
}
}
}
Now that I had methods to change the dates to the correct formats. On the _form page I declared at the top, under the initiation of the form.
$model->date_required = Custom::reformatDate($model->date_required);
$model->date_created = Custom::reformatDate($model->date_created);
$model->date_completed = Custom::reformatDate($model->date_completed);
This now results in the date being shown correctly, both when the _form page is viewed and the date is changed via the CJuiDatePicker as i still use the dateFormat option to show the correct format when the date is changed.
Lastly I added to both the create and update actions of the controller the following.
if(isset($_POST['Tickets']))
{
$model->attributes=$_POST['Tickets'];
$model->date_created = Custom::formatDate($model->date_created);
$model->date_required = Custom::formatDate($_POST['Tickets']['date_required']);
$model->date_completed = Custom::formatDate($_POST['Tickets']['date_completed']);
if($model->save())
So before the data is then saved back to the database I format the date to the correct format and pop it into the database.
I'm not expert and only a few month into Yii and about 9 months into PHP. I know there are all sorts of before and after save methods and this may not be the best way to do it, in fact if there is a better way I am all ears. But for now this is working for me. hope ths helps someone.
/* Small Update */
After speaking with a colleague who has been doing this stuff for about a decade. he said it would be much cleaner to remove the code I placed on the form page under the form initiation and move it rather into the controller, so for example my update method appears like so
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$model->date_required = Custom::reformatDate($model->date_required);
$model->date_created = Custom::reformatDate($model->date_created);
$model->date_completed = Custom::reformatDate($model->date_completed);
So rather than reformatting the dates on the form page, it is done directly after loadModel, keeping the view cleaner.
I have generated my crud screens using gii.. I have a search form, where i have put a date picker, where i give the user to select the date he wants.
But the problem is that i have the date stored in seconds in the database.
and i know that i can convert the date using strtotime. But then how do i filter using the search method in my model?
this is my date picker
<?php
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'name'=>'ordering_date',
'id'=>'ordering_date',
// additional javascript options for the date picker plugin
'options'=>array(
'showAnim'=>'fold',
),
'htmlOptions'=>array(
'style'=>'height:20px;'
),
));
?>
and this is my search method in my model. I want to compare the ordering_date
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
//echo $this->ordering_date;
$criteria=new CDbCriteria;
$criteria->compare('order_id',$this->order_id);
$criteria->compare('customer_id',$this->customer_id);
$criteria->compare('delivery_address_id',$this->delivery_address_id);
$criteria->compare('billing_address_id',$this->billing_address_id);
$criteria->compare('ordering_date',$this->ordering_date);
$criteria->compare('ordering_done',$this->ordering_done,true);
$criteria->compare('ordering_confirmed',$this->ordering_confirmed);
$criteria->compare('payment_method',$this->payment_method);
$criteria->compare('shipping_method',$this->shipping_method);
$criteria->compare('comment',$this->comment,true);
$criteria->compare('status',$this->status,true);
$criteria->compare('total_price',$this->total_price);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Try this:
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'model'=>$model,
'attribute'=>'ordering_date',
'options' => array('dateFormat' => 'mm-dd-yy',),
And search
$begindate = CDateTimeParser::parse($this->ordering_date, 'MM-dd-yyyy');
$enddate = $begindate + 24* 60*60;
$criteria->addBetweenCondition('ordering_date', $begindate, $enddate);
Either do a $this->ordering_date = strtotime($this->ordering_date); before you compare or $criteria->compare('ordering_date', strtotime($this->ordering_date));
I want to display some text in a CDetailView which was previously encoded in MarkDown format.
this is my view code:
<?php
$this->widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
'title',
array(
'name'=>'text',
'type'=>'raw',
'value'=>$this->markdown->transform($model->text)
),
'author_id',
'date_added',
),
));
?>
and in my controller, I instantiate a CMarkDown filter like this:
private $_markdown = null;
public function getMarkdown()
{
if ( $this->_markdown === null)
{
$this->_markdown = new CMarkdown();
$this->_markdown->purifyOutput = true;
}
return $this->_markdown;
}
notice how I explicitly set purifyOutput to true.
So I created a mock post full of things like marquee and injected javascript to see how it would behave and it didn't filter anything at all!! I got an alert on my face and the marquee was all happy moving around on the page....
I found a workaround which was to set 'type'=>'html' in the CDetailView but I shouldn't need to do that, should I??
Isn't that purifyOutput option supposed to filter unwanted stuff out for me when I call the ->transform() method??
Some help, please.
To purify the output you need to use CMarkdown::processOutput, not the transform method (that one is more low-level and does not honor purifyOutput).
If you look at the documentation carefully, you will notice that processOutput mentions the purifyOutput setting while transform does not. Viewing the source confirms this.