I am using the date format in my php controller like
$meter->created_at = date('Y-m-d H:i:s');
But the output I am getting is 2017-11-29 00:00:00
I have also checked this solution.
Update 1
I am inserting some data via excel file.
foreach($final_data as $key=>$value)
{
if($key <= $header_index) continue;
$meter = new Meters;
foreach($value as $k=>$v){
$v = preg_replace('/\s+/', ' ', trim($v));
if(isset($fieldSet[0]['meter_msn']) && $fieldSet[0]['meter_msn']==$k){
$meter->meter_msn =$v."";
// echo $v.", ";
}
if(isset($fieldSet[0]['description']) && $fieldSet[0]['description']==$k){
$meter->description = $v;
}
if (isset($fieldSet[0]['status']) && $fieldSet[0]['status'] == $k) {
$meter->status = $v;
}
if (isset($fieldSet[0]['meter_status']) && $fieldSet[0]['meter_status'] == $k) {
$meter->meter_status = $v;
}
if (isset($fieldSet[0]['historic']) && $fieldSet[0]['historic'] == $k) {
$meter->historic = $v;
}
}
$meter->created_at = date('Y-m-d H:i:s');
if($meter->save())
$ok_count++;
else
$status_arr[] = $meter->errors;
}
Any help would be highly appreciated.
Keep the datatype for date fields like created_at and update_at as int and use TimestampBehaviour in your model.
By default, TimestampBehavior will fill the created_at and updated_at attributes with the current timestamp when the associated AR object is being inserted. it will fill the updated_at attribute with the timestamp when the AR object is being updated. The timestamp value is obtained by time() and whenever and where ever you want to show the date you can format it using php's date() function no need to make it complex when the framework itself can do it via conventional approach.
You might have to make little change for renaming the columns to created_at and updated_at and then include the TimestampBehaviour like below in your model.
use yii\behaviors\TimestampBehavior;
public function behaviors() {
return [
TimestampBehavior::className(),
];
}
Or if you want to use the column names as is you can use the following approach to map you field names
use yii\db\Expression;
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'create_time',
'updatedAtAttribute' => 'update_time',
'value' => new Expression('NOW()'),
],
];
}
TimestampBehavior also provides a method named touch() that allows you to assign the current timestamp to the specified attribute(s) and save them to the database. For example,
$model->touch('creation_time');
Related
I am using Yii2 basic. I have a table called groupsavingdetails which saves monthly groups saving.
I have records for Group with Id 29 and from Year 2017 and month August. Similarly I have the records for this particular group from 2017 September, October, November and December. Also there are data for this group for Year 2018 and Months January and March as shown in image.
The process is that For month August there was no entry for this group (i.e, it was the first time data entry, so Opening Balance is set to 0). Now for september the closing balance of August is taken as the Opening Balance and so on. So these are dependent.
Now the situation is when I want to change September months record, then its closing balance will get changed and thus this new closing balance will be set to opening balance for the October month and so on. How should I do this?
Below is the actionUpdate function which gives me error as Call to a member function save() on array
public function actionUpdate($id) {
$model = $this->findModel($id);
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if ($model->load(Yii::$app->request->post())) {
$count = Yii::$app->db->createCommand('SELECT COUNT(*) FROM groupsavingdetails WHERE ((groupsavingdetails.GroupId=:Id and Year>=:year and Month>:month) OR (GroupId=:Id and Year>:year AND Month>0))')->bindValues([':Id' => $model->GroupId, ':year' => $model->Year, ':month' => $model->Month]->queryAll();
if ($count == 0) {
}
if ($count == 1) {
}
if ($count > 1) {
if ($model->LoanGiven != 0) {
$model->TotalValueofLoanGiven += $model->LoanGiven;
}
if ($model->LoanRecovery != 0) {
$model->LoanRepaidUptilNow += $model->LoanRecovery;
}
$model->TotalValueOfLoanOutstanding = $model->TotalValueofLoanGiven - $model->LoanRepaidUptilNow;
$model->ClosingBalance = ($model->OpeningBalance + $model->TotalSaving + $model->LoanRecovery + $model->LoanInterest + $model->Fine + $model->BankInterest + $model->BankLoan - $model->Expenses - $model->LoanGiven);
$groups = Yii::$app->db->createCommand('SELECT * FROM groupsavingdetails WHERE ((groupsavingdetails.GroupId=:Id and Year>=:year and Month>:month) OR (GroupId=:Id and Year>:year AND Month>0))')->bindValues([':Id' => $model->GroupId, ':year' => $model->Year, ':month' => $model->Month])->queryAll();
foreach ($groups as $k => $group) {
if ($k == 0) {
$groups[$k]['OpeningBalance'] = $model->ClosingBalance;
$groups[$k]['TotalValueofLoanGiven'] = $model->TotalValueofLoanGiven;
$groups[$k]['LoanRepaidUptilNow'] = $model->LoanRepaidUptilNow;
$groups[$k]['TotalValueOfLoanOutstanding'] = $model->TotalValueOfLoanOutstanding;
}
}
$groups->save(); // Here it gives me error even if i write $groups[$k]->save()
$model->save();
return $this->redirect(['view', 'id' => $model->GroupSavingDetailsId]);
}
} else {
return $this->render('update', ['model' => $model,]);
}
}
You can't call save() (or any other function) on an array. Functions are called on objects. So you'll have to make sure you have an object, load the data onto the object and then save that object. You could do it like this:
foreach ($groups as $k => $group) {
if ($k === 0) {
$groupModel = new GroupSavingDetails(); // Or whatever the model is called..
// Load the data onto the model
$groupModel->OpeningBalance = $model->ClosingBalance;
$groupModel->TotalValueofLoanGiven = $model->TotalValueofLoanGiven;
$groupModel->LoanRepaidUptilNow = $model->LoanRepaidUptilNow;
$groupModel->TotalValueOfLoanOutstanding = $model->TotalValueOfLoanOutstanding;
// Save the model
$groupModel->save();
}
}
// Don't save $groups after the foreach, because that's still an array
This will (probably/hopefully) fix the code. But it might still not be the best way to do it. It seems like you could also accomplish updating all these records with just one UPDATE query. I did not test the code below, but this would create an update query that can be modified to update the correct rows. This way you don't have to retrieve all the individual records, update them one by one and the run an update command for each row.
Yii::$app->createCommand()->update(
'groupsavingdetails', // Or GroupSavingDetails::tableName()
[
'OpeningBalance' => $model->ClosingBalance;
'TotalValueofLoanGiven' => $model->TotalValueofLoanGiven,
'LoanRepaidUptilNow' => $model->LoanRepaidUptilNow,
'TotalValueOfLoanOutstanding' => $model->TotalValueOfLoanOutstanding,
],
[
'OR',
[
'AND',
['GroupId' => $model->groupId],
['>=', 'Year', $model->Year],
['>', 'Month', $model->Month],
],
[
'AND',
['GroupId' => $model->groupId],
['>', 'Year', $model->Year],
['>', 'Month', 0],
],
]
)->execute()
I want to store the current date time in MySQL using the following Laravel function. Actually, I stored a static date. Instead of this, how can I store the current date time in the created_at and updated_at fields in the database?
function insert(Request $req)
{
$name = $req->input('name');
$address = $req->input('address');
$data = array("name" => $name, "address" => $address, "created_at" => '2017-04-27 10:29:59', "updated_at" => '2017-04-27 10:29:59');
DB::table('student')->insert($data);
echo "Record inserted successfully.<br/>";
return redirect('/');
}
Use the Laravel helper function
now()
Otherwise, use the carbon class:
Carbon\Carbon::now()
It is used like this:
$data = array("name" => $name,"address" => $address,"created_at"=> Carbon::now(),"updated_at"=> now());
DB::table('student')->insert($data);
For more information, see now()
You can also use this to get the current date time. It's working.
$current_date = date('Y-m-d H:i:s');
And also I have updated and set things in your function. You have to add this:
function insert(Request $req)
{
$name = $req->input('name');
$address = $req->input('address');
$current_date_time = date('Y-m-d H:i:s');
$data = array("name" => $name,
"address" => $address,
"created_at" => $current_date_time,
"updated_at" => $current_date_time);
DB::table('student')->insert($data);
echo "Record inserted successfully.<br/>";
return redirect('/');
}
Use this in your database query:
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
You can use the DateTime object.
Look at the below code:
$curTime = new \DateTime();
$created_at = $curTime->format("Y-m-d H:i:s");
$updateTime = new \DateTime();
$updated_at = $updateTime->format("Y-m-d H:i:s");
Use
use Carbon\Carbon;
at the header of the controller. This code work for Laravel 9:
$updated = Carbon::now();
You may save it inside a variable and use the variable for inserting and updating statements or for any other purpose.
During migration, I defined the column check_at as datetime. And I used the following command for table creation.
php artisan migrate
It generates a timestamp-type column in MySQL. I am passing the variable $updated for update purposes. While using phpMyAdmin, I can see the column check_at has data in date-time format.
Hello Silverstripe Specialists!
I made the tutorial "extending a basic site"
(http://doc.silverstripe.org/en/tutorials/extending_a_basic_site)
That all worked very well so far.
I made this to show the latest news on the HomePage:
In HomePage.php:
// ...
public function LatestNews($num=5) {
$holder = ArticleHolder::get()->First();
return ($holder) ? ArticlePage::get()->filter('ParentID',
$holder->ID)->sort('Date DESC')->limit($num) : false;
}
And this in HomePage.ss:
// ...
public function LatestNews($num=5) {
$holder = ArticleHolder::get()->First();
return ($holder) ? ArticlePage::get()->filter('ParentID',
$holder->ID)->sort('Date DESC')->limit($num) : false;
}
That works very well!
Now my Question: All my News have a Date-Field. Is it possible to show only
the News of the current Date on the HomePage?
I tried this, but this wont work (Server Error) (Datum is my Date of the News):
public function LatestNews($num) {
$holder = ArticleHolder::get()->First();
return ($holder) ? ArticlePage::get()->filter('ParentID', "datum == CURDATE()",
$holder->ID)->sort('Date DESC')->limit($num) : false;
}
Thank you very much for your help!
filter() needs either two values (column and value) or an array of key-value pairs of what to filter. So if you want to filter for more than one thing you need an array as parameter:
$today = date('Y-m-d');
$todaysNews = ArticlePage::get()->filter(array(
'ParentID' => $holder->ID,
'datum' => $today
));
This will return a DataList you can sort and limit like you did in your example.
See also in docs:
Data Model and ORM general overview
Search filters how to filter "greater than" etc...
EDIT:
So a method in your controller could look like:
public function getTodaysNews($num=5) {
$holder = ArticleHolder::get()->First();
$today = date('Y-m-d');
return $holder
? ArticlePage::get()->filter(array(
'ParentID' => $holder->ID,
'datum' => $today
))->sort('Date DESC')->limit($num)
: false;
}
I have a date column that usually takes values as dd.MM.yyyy. Its validation rule in the model's rules() is this:
array('start, end', 'date', 'format' => 'dd.MM.yyyy'),
I'm populating the database from a CSV file, and I'd like to be able to set the date to NULL (i.e. nothing) if the CSV record is empty. So, I'm doing:
if (empty($csv_data)) {
$user->start = new CDbExpression('NULL');
} else {
$user->start = $csv_data;
}
But I get an error that the date format is invalid. Why is that?
The CDateValidator documentation says that the allowEmpty property is true by default, so it should be able to set this to NULL, right? Note that if I just assing the "" string to the date, it'll convert it to a 0000-00-00 00:00:00 timestamp, which is not NULL.
in model rules():
array('start, end', 'date', 'format' => 'dd.MM.yyyy'),
array('start, end', 'default', 'setOnEmpty' => true, 'value' => null),
also,
if (empty($csv_data)) {
$user->start = null;
} ...
should do the trick too.
The trivial fix for this is not to set the value at all during creation:
if (!empty($csv_data)) {
$user->start = $csv_data;
}
This way, the date will not be set and thus appear as empty, which also passes validation.
Assigning a CDbExpression to the field will (and should) never pass validation; the validator allows null but it definitely cannot allow an arbitrary CDbExpression as the value of the field; this should not be surprising.
If you wanted to write null to the database then do it simply with $user->start = null -- there is no reason to involve CDbExpression at all here.
Another approach you could use in case you did need to use CDbExpression would be to tell save not to validate the record and do it manually, as in:
$attributes = $user->attributeNames();
if (empty($csv_data)) {
$user->start = new CDbExpression('NULL');
$attributes = array_diff($attributes, array('start')); // don't validate this
} else {
$user->start = $csv_data;
}
if ($user->validate($attributes)) { // validate only attributes we want here
$user->save(false); // no validation at all here
}
I wanted to specify the output of a field from within my model so I added a date key to my $_schema:
models/Tags.php
<?php
protected $_schema = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'title' => array('type' => 'string'),
'created' => array('type' => 'integer', 'date' => 'F jS, Y - g:i a'),
'modified' => array('type' => 'integer')
);
?>
I store my time as an unsigned integer in the db (output of time()).
I want my base model to format any field that has the date key for output. I thought the best place to do that would be right after a find:
extensions/data/Model.php
<?php
static::applyFilter('find', function($self, $params, $chain) {
$schema = $self::schema();
$entity = $chain->next($self, $params, $chain);
foreach ($schema as $field => $options) {
if (array_key_exists('date', $options)) {
//format as a date
$params['data'][$field] = $entity->formatDate($field, $options['date']);
}
}
return $entity;
});
public function formatdate($entity, $field, $format, $timezone = 'Asia/Colombo') {
$dt = new \DateTime();
$tz = new \DateTimeZone($timezone);
$dt->setTimestamp($entity->$field);
$dt->setTimezone($tz);
return $dt->format($format);
}
?>
This doesn't seem to be working. When I execute a find all, this filter seems to get hit twice. The first time, $entity contains a count() of the results and only on the second hit does it contain the Records object.
What am I doing wrong? How do I alter this so that simply doing <?= $tag->created; ?> in my view will format the date the way I want? This, essentially, needs to be an 'after filter', of sorts.
EDIT
If I can find a way to access the current model entity object (not the full namespaced path, $self contains that), I can probably solve my problem.
Regardless of a small fix for your after find filter, I would do it differently.
Every time you'll do a find, you'll override your date format, even if you don't want to display it, but only do a business logic like comparing dates etc ...
Since you want to format your output only in your views (we are not talking about formatting on the fly json responses for an API, etc.), why not using a helper method ?
An other way is to add an instance method in your model (or a BaseModel), called created_at(). Then, you will call it from a view with <?= $entity->created_at() ?>
You can still force a format fetched from your $_schema, or pass it as a param, etc ...
A helper seems cleaner as we are talking about presenting data in your views.
I'm reading the OP's problem as the find filter executes twice. If that's right, then why not just check to see if the $entity contains a recordset?