Converting readable date to mysql date with AttributeBehavior in Yii2 - yii2

Trying to convert a date formatted as M d, yyyy to save to the database as Y-m-d so I've setup my behavior:
public function behaviors() {
return [
[
'class' => AttributeBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => [ 'date_available' ],
ActiveRecord::EVENT_BEFORE_UPDATE => [ 'date_available' ],
],
'value' => function ( $event ) {
return date( 'Y-m-d', strtotime( $this->date_available ) );
},
],
]
}
however upon save, the database field is 0000-00-00. If I do it in the actionUpdate:
$model->date_available = date( 'Y-m-d', strtotime( $model->date_available ) );
it works fine

Here is a working example on Yii2 2.0.10
Add the model class with the behaviors method. Also note the string transformation if the date is being returned in mm/dd/yyyy to mm-dd-yyyy then convert to DB date format and save.
public function behaviors() {
return [
[
'class' => AttributeBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['start_date'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['start_date'],
],
'value' => function ($event) {
return date('Y-m-d', strtotime($this->start_date));
},
],
[
'class' => AttributeBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['stop_date'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['stop_date'],
],
'value' => function ($event) {
return date('Y-m-d', strtotime($this->stop_date));
},
],
];
}

in behave,$this->date_available is empty.in $value, you can't use $this->date_available.

Related

Log not working in yii2

i want to put a log in app.log ,My config file
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
'file' => [
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
'logFile' => '#root/console/runtime/logs/app.log',
],
]
]
in controller action
public function actionRankCalculation()
{
$allConest = Contest::find()->where('isActive = 1')->all();
Yii::trace('start calculating average revenue');
$response = [];
/** #var Contest $contest */
foreach ($allConest as $contest) {
$videoQuery = Video::find()->where('contest_id = ' . $contest->id);
$videoQuery->andWhere('isActive = 1');
$videoQuery->orderBy([
'global_likes' => SORT_DESC,
'id' => SORT_ASC,
]);
}
But Yii::trace('start calculating average revenue'); not working
You try this.Use categories. For example like below
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error'],
'categories' => ['test1'],
'logFile' => '#app/Test/test1.log',
],
And use below one in controller action
public function actionIndex(){
Yii::error('Test index action', $category = 'test1'); }
Try to set both flushInterval and exportInterval to 1 in console config:
return [
'bootstrap' => ['log'],
'components' => [
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'exportInterval' => 1,
],
],
'flushInterval' => 1,
],
],
];
It makes each log message appearing immediately in logs.

Yii2 RESTFUL API without models: getting 404 response

I'm implementing RESTFUL API with Yii2. The thing is I don't use models at all. My API just gets the request and performs some calculations (or passes request as a proxy to somewhere else) and outputs the response.
I have following controllers in app\modules\api\v1\controllers:
namespace app\modules\api\v1\controllers;
class CarController extends \yii\rest\Controller
{
// GET /v1/car/:id
public function actionIndex()
{
$carId = \Yii::$app->request->get('id');
// Forwarding request to other API
return ['some_reponse'];
}
// DELETE /v1/car/:id
public function actionDelete()
{
$carId = \Yii::$app->request->get('id');
// Forwarding request to other API
return ['some_reponse'];
}
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
'create' => ['post'],
'delete' => ['delete']
],
],
];
}
}
// ===============================
namespace app\modules\api\v1\controllers;
class CarsController extends \yii\rest\Controller
{
// POST /v1/cars
public function actionCreate()
{
$carData = \Yii::$app->request->post;
// Forwarding data to other API
return ['some_reponse'];
}
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
'create' => ['post']
],
],
];
}
}
// ===============================
namespace app\modules\api\v1\controllers;
class NotificationsController extends \yii\rest\Controller
{
// POST /v1/notifications
public function actionCreate()
{
$noticicationsData = \Yii::$app->request->post;
// Perform some additinal actions here
return ['some_reponse'];
}
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
'create' => ['post']
],
],
];
}
}
Url manager configuration:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/cars' ],
'extraPatterns' => [ 'POST cars' => 'create' ]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/car' ],
'extraPatterns' => [ 'GET car' => 'index', 'DELETE car' => 'delete' ]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/notifications' ],
'extraPatterns' => [ 'POST notifications' => 'create' ]
]
]
]
Cars endpoint works fine. But other endoints return 404 error. Error response example:
{
"name": "Not Found",
"message": "Page not found.",
"code": 0,
"status": 404,
"type": "yii\web\NotFoundHttpException",
"previous": {
"name": "Invalid Route",
"message": "Unable to resolve the request: v1/car/options",
"code": 0,
"type": "yii\base\InvalidRouteException"
}
}
Any ideas whats wrong here? I guess something is wrong with my rules.
The problem was with urlManager rules configuration. For e.g. if I create CarController it treats like CarsController. So I have to set pluralize to false. Also modified extraPatterns section as well:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/cars' ],
'extraPatterns' => [ 'POST' => 'create' ],
],
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/car' ],
'extraPatterns' => [ 'GET' => 'index', 'DELETE' => 'delete' ],
'pluralize' => false
],
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/notifications' ],
'extraPatterns' => [ 'POST' => 'create' ]
]
]
]
Problem with yii\rest\Controller::actions(), this method already have actions index , options,view etc. You need disabled action to use your action:
public function actions()
{
$actions = parent::actions();
unset($actions['view'], $actions['index']);
return $actions;
}

Yii2 View DateTime Format (d-m-Y H:i:s) But When Save/update in DB Change format to Y-m-d H:i:s

I'm Using Kartik DateTimePicker Extension
<?= $form->field($model, 'Created')->widget(DateTimePicker::classname(),[
'model' => $model,
'attribute' => 'Created',
'name' => 'Created',
'options' => ['placeholder' => 'Select Created'],
'pluginOptions' => [
'format' => 'dd-mm-yyyy hh:ii:ss',
'todayHighlight' => true
]
])
?>
User fill the Create Date the format is
d-m-Y H:i:s (like 24-09-2015 11:21:10)
But when record save to database then Create Date Format change to
Y-m-d H:i:s (like 2015-09-24 11:21:10)
How can I change the date format on save/update of record
Need to just add this code before save/update model in controller.
like,
// ICU format
$model->Created = Yii::$app->formatter->asDate($_POST['modelName']['Created'], 'yyyy-MM-dd HH:mm:ss'); // 2014-10-06 15:22:34
OR
// PHP date()-format
$model->Created = Yii::$app->formatter->asDate($_POST['modelName']['Created'], 'php:Y-m-d H:i:s'); // 2014-10-06 15:22:34
For more information refer this link
Finally I found the answer using AttributeBehavior.
In my model class I've write the behaviors code:
public function behaviors()
{
return [
[
'class' => AttributeBehavior::className(),
'attributes' => [
// update 1 attribute 'created' OR multiple attribute ['created','updated']
ActiveRecord::EVENT_BEFORE_INSERT => ['created','updated'],
ActiveRecord::EVENT_BEFORE_UPDATE => 'updated',
],
'value' => function ($event) {
return date('Y-m-d H:i:s', strtotime($this->Created));
},
],
];
}
My Model Class
namespace frontend\models;
use Yii;
use yii\db\ActiveRecord;
use yii\behaviors\AttributeBehavior;
/**
* This is the model class for table "product".
*
* #property integer $id
* #property integer $product_id
* #property string $product_name
* #property string $created
* #property string $updated
*/
class Product extends ActiveRecord
{
public $csv_file;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'product';
}
public function behaviors()
{
return [
[
'class' => AttributeBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created','updated'], // update 1 attribute 'created' OR multiple attribute ['created','updated']
ActiveRecord::EVENT_BEFORE_UPDATE => 'updated', // update 1 attribute 'created' OR multiple attribute ['created','updated']
],
'value' => function ($event) {
return date('Y-m-d H:i:s', strtotime($this->LastUpdated));
},
],
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'product_id', 'product_name', created, updated], 'required'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'product_id' => 'Product ID',
'product_name' => 'Product Name',
'created' => 'Created',
'updated' => 'Updated',
];
}
}
If input format is d/m/Y then you need to replace the "/" by "-"
like: input date(created): 10/09/2015
date('Y-m-d H:i:s', strtotime(str_replace("/","-",$this->created)));
use in active form
'clientOptions' => ['alias' => 'dd-mm-yyyy'],
use in active form
echo MaskedInput::widget([
'name' => 'input-31',
'clientOptions' => ['alias' => 'date']]);
use class
Class yii\widgets\MaskedInput
Example
<?= $form->field($model, 'date_of_birth')->widget(\yii\widgets\MaskedInput::className(), [
'name' => 'input-31',
'clientOptions' => ['alias' => 'dd-mm-yyyy'], ]) ?>
I have simple code,
in behavior:
public function behaviors() {
return [
[ 'class' => \yii\behaviors\TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
],
// if you're using datetime instead of UNIX timestamp:
'value' => new Expression('NOW()'),
]
];
}
for rules:
public function behaviors() {
return [
[ 'class' => \yii\behaviors\TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
],
// if you're using datetime instead of UNIX timestamp:
'value' => new Expression('NOW()'),
]
];
}
public function behaviors() {
return [
[
'class' => BlameableBehavior::className(),
],
[
'class' => TimestampBehavior::className(),
'value' => date('Y-m-d H:i:s')
],
];
}

Override default sort for ActiveDataProvider in Yii2

I have a lot of models using created_time. And I want all of the GridViews to show the models sorted by created_time DESC.
Right now I write something like this
$dataProvider = new \yii\data\ActiveDataProvider([
'query' => MyModel::find(),
'sort' => [
'defaultOrder' => [
'created_time' => SORT_DESC
]
],
]);
Instead of writing all of sort configuration I tried ways below but nothing works.
Using container
\Yii::$container->set(\yii\data\ActiveDataProvider::class,
[
'sort' => [
'defaultOrder' => [
'created_time' => SORT_DESC
]
]
]);
Overriding the sort in extended class.
class ActiveDataProvider extends \yii\data\ActiveDataProvider {
public $sort = [
'defaultOrder' => [
'created_time' => SORT_DESC
]
];
}
Overriding before init() in the extended class works, but it won't work if the instantiation tries to override again.
class ActiveDataProvider extends \yii\data\ActiveDataProvider {
public function init() {
$this->sort = [
'defaultOrder' => [
'created_time' => SORT_DESC
]
];
parent::init();
}
}
//but this won't work if I want to use the ascending
$dataProvider = new \app\components\data\ActiveDataProvider([
'query' => MyModel::find(),
'sort' => [
'defaultOrder' => [
'created_time' => SORT_ASC
]
],
]);
To do this for a single GridView, you can add 'defaultOrder' => ['created_time' => SORT_DESC] to the array that is accepted by setSort():
$dataProvider->setSort([
'attributes' => [
'id',
...
],
'defaultOrder' => ['created_time' => SORT_DESC]
]);
You should do this for yii\data\Sort and not for yii\data\ActiveDataProvider. See the documentation to $sort property.
1) With container:
use Yii;
...
Yii::$container->set(\yii\data\Sort::className(),
'defaultOrder' => [
'created_time' => SORT_DESC,
],
]);
2) Overriding class:
class Sort extends yii\data\Sort
{
public $defaultOrder' = [
'created_time' => SORT_DESC,
];
}

TimestampBehavior is not working in Yii2

public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
'access' => [
'class' => AccessControl::className(),
'only' => ['create', 'update', 'delete', 'view', 'index'],
'rules' => [
// allow authenticated users
[
'allow' => true,
'roles' => ['#'],
],
// everything else is denied by default
],
],
[
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['create_time', 'update_time'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['update_time'],
],
],
];
}
Above code is for my controller behavior function. While creating or updating, 'create_time' and 'update_time' fields are not getting updated by current time. Type of those fields are set to datetime. Please need your help.
You have to declare it in the behaviors method of your model.
To use TimestampBehavior, insert the following code to your ActiveRecord class
public function behaviors()
{
return [
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['create_time', 'update_time'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['update_time'],
],
];
}
Try this, it works for me:
use yii\db\Expression;
...
[
'class' => TimestampBehavior::className(),
'updatedAtAttribute' => 'update_time',
'value' => new Expression('NOW()'),
],
You can also use
'value' => date('Y-m-d H:i:s')
if you would like to use the PHP datetime.
I used new Expression('NOW()') to store current timestamp. But It does't store the date based on current timezone. Instead it stores based on server time.
I just used normal php date function to solve this.
eg :
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
public function behaviors()
{
return [
'timestamp' => [
'class' => 'yii\behaviors\TimestampBehavior',
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
'value' => date('Y-m-d H:i:s'),
],
];
}
You must also add the value and use the class Expression
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
public function behaviors()
{
return [
'timestamp' => [
'class' => 'yii\behaviors\TimestampBehavior',
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
'value' => new Expression('NOW()'),
],
];
}