Sample data in my collection :
created_at : 2018-04-29 05:25:28.000Z
I'm using TimestampBehavior,
'timestamp' => [
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'created_at',
ActiveRecord::EVENT_BEFORE_UPDATE => 'updated_at',
],
'value' => function() { $now = new \DateTime('NOW'); return new \MongoDB\BSON\UTCDateTime(strtotime($now->format("Y-m-d H:i:s"))*1000); },
],
This is my count function :
public function count_users () {
$cnt = Users::find ()->select (['_id', 'created_at'])->where (['created_at'=>date ('Y-m-d')])->all ();
return count ($cnt);
}
How to use find select with a date?
You could use the count() function
You could use the count() function and new Expression('NOW()')
public function count_users () {
$cnt = Users::find ()->select (['_id', 'created_at'])
->where (['created_at' => new \yii\db\Expression('curdate()')]->count();
retur $cnt;
}
yii-db-query
yii-db-query#count()-detail
Change your where condition like below and try
public function count_users () {
$cnt = Users::find ()->where('DATE(created_at)=CURDATE()')->count();
return $cnt;
}
yii-db-query#count()-detail
You can reduce it to one-liner by using count() as per suggestions above or using scalar()
scalar(): returns the value of the first column in the first row of
the query result.
public function count_users(){
return Users::find()
->select([new \yii\db\Expression('COUNT(id) as total')])
->where(['DATE(created_at)'=>new \yii\db\Expression('CURDATE()')])
->scalar();
}
Related
Model
class ClickMeeting extends Model
{
protected $table = 'clickmeeting';
public $timestamps = false;
protected $dateFormat = 'U';
protected $guarded = ['id'];
static $videoDemoSource = ['upload', 'youtube', 'vimeo', 'external_link'];
public function ClickMeeting()
{
///
}
}
Controller
public function dashboard()
{
$client = new Client();
$uri = 'https://api.clickmeeting.com/v1/conferences/active';
$header = ['headers' => ['X-Api-Key' => 'xxxxxxxxxxxxxxxxxxxxxxxx']];
$res = $client->get($uri, $header);
$conferences = json_decode($res->getBody()->getContents(), true);
// dd($conferences);
collect($conferences)
->each(function ($conference, $key) {
ClickMeeting::firstOrCreate([
'parent_id' => $conference['parent_id'],
'room_type' => $conference['room_type'],
'room_url' => $conference['room_url'],
],
[
'starts_at' => $conference['starts_at'],
'ends_at' => $conference['ends_at'],
'room_pin' => $conference['room_pin'],
'title' => $conference['name'],
'name_url' => $conference['name_url'],
'access_type' => $conference['access_type'],
'lobby_enabled' => $conference['lobby_enabled'],
'lobby_description' => $conference['lobby_description'],
'registration_enabled' => $conference['registration_enabled'],
'status' => $conference['status'],
'timezone' => $conference['timezone'],
'timezone_offset' => $conference['timezone_offset'],
'paid_enabled' => $conference['paid_enabled'],
'automated_enabled' => $conference['automated_enabled'],
'type' => $conference['type'],
'permanent_room' => $conference['permanent_room'],
'embed_room_url' => $conference['embed_room_url']
]);
});
$conferences = ClickMeeting::get();
return view('admin.clickmeeting.dashboard',compact('conferences'));
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime
value: '2022-06-22T16:10:00+00:00' for column 'starts_at' at row 1
(SQL: insert into clickmeeting (parent_id, room_type,
room_url, starts_at, ends_at, room_pin, title, name_url,
access_type, lobby_enabled, lobby_description,
registration_enabled, status, timezone, timezone_offset,
paid_enabled, automated_enabled, type, permanent_room,
embed_room_url) values (?, webinar,
https://abc.clickmeeting.com/urinary-tract-infection-in-children,
2022-06-22T16:10:00+00:00, 2022-06-22T17:10:00+00:00, 477736894,
URINARY TRACT INFECTION IN CHILDREN,
urinary-tract-infection-in-children, 1, 1, , 1, active, Africa/Accra,
0, 0, 0, 0, 0,
https://abc.clickwebinar.com/embed_conference.html?r=123456))
I keep getting Invalid datetime format: 1292 Incorrect datetime value. Help is greatly appreciated. Thank you
I think these occur because the DATETIME value in the statement above uses a format that is not supported by MySQL, you can use the STR_TO_DATE() function for passing the starts_at variable into the database.
The code like
'starts_at' => STR_TO_DATE($conference['starts_at'], "%m-%d-%Y %H:%i:%s"),
Please check this link you can find more about the STR_TO_DATE() function
Try use Carbon\Carbon for assigning your dates:
collect($conferences)
->each(function ($conference, $key) {
ClickMeeting::firstOrCreate([
....
],
[
'starts_at' => Carbon::parse($conference['starts_at']),
'ends_at' => Carbon::parse($conference['ends_at']),
....
]);
});
Alternatively, you could tell laravel which fields are date using the $casts property:
class ClickMeeting extends Model
{
....
protected $guarded = ['id'];
protected $casts = [
'starts_at' => 'datetime',
'ends_at' => 'datetime'
];
....
}
I have this problem: I need to get data from database and filter them. but then I need to use custom php function to filter those filtered results using data from it.
Clasic search function in ActiveDataProvider
public function search($params) {
$query = Passenger::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// I guess my function would go like here
Passenger::filterResultsEvenMore($dataProvider);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'passenger_id' => $this->passenger_id,
// ...
'version' => $this->version,
'status' => $this->status,
]);
return $dataProvider;
}
So my question is how to work with results of dataProvider because if I vardump the variable it looks like this and no actual data there.
yii\data\ActiveDataProvider Object
(
[query] => common\models\PassengerQuery Object
(
[sql] =>
[on] =>
[joinWith] =>
[select] =>
[selectOption] =>
[distinct] =>
[from] =>
[groupBy] =>
[join] =>
[having] =>
[union] =>
[params] => Array()
[_events:yii\base\Component:private] => Array()
[_behaviors:yii\base\Component:private] => Array()
[where] => Array
(
[status] => 1
)
[limit] =>
[offset] =>
[orderBy] =>
[indexBy] =>
[emulateExecution] =>
[modelClass] => common\models\Passenger
[with] =>
[asArray] =>
[multiple] =>
[primaryModel] =>
[link] =>
[via] =>
[inverseOf] =>
)
[key] =>
[db] =>
[id] =>
[_sort:yii\data\BaseDataProvider:private] =>
[_pagination:yii\data\BaseDataProvider:private] =>
[_keys:yii\data\BaseDataProvider:private] =>
[_models:yii\data\BaseDataProvider:private] =>
[_totalCount:yii\data\BaseDataProvider:private] =>
[_events:yii\base\Component:private] => Array()
[_behaviors:yii\base\Component:private] =>
)
UPDATE
I need to use function like this for each record:
if (myFunction(table_column_1, table_column_2)) {
result_is_ok_return_it
} else {
do_not_return_this_record
}
Why do you don't add your additional filters to query object used in DataProvider?
You can parse your conditions to $query->andFilterWhere(). If you need custom function for it just modify $dataProvider->query object inside function. After execute query in data provider you can only filter results by manually filter array of models stored in $dataProvider->models
To get result use models property or getModels()
For example,
$dataProvider->models;
OR
$dataProvider->getModels();
I think I came across a solution, (looks like it is working)
http://www.yiiframework.com/doc-2.0/yii-data-basedataprovider.html#setModels()-detail
After I do all my usual search stuff as described in question at beginning, I would do something like this using setModels() function
class PassengerSearch extends Passenger
public $status; // virtual attribute not present in database table
public function rules()
{
return [
// ... some other rules
[['status'], 'safe'],
];
}
// ...
$filtered_models = [];
$filter_models = false; // if you only want to filter if there is some value
foreach ($dataProvider->models as $model) {
// if ($model->status == 1) // example
if (!empty($this->status) && $model->status == $this->status) { // better approach, using virtual attribute $status
$filter_models = true;
$filtered_models[] = $model;
}
}
if ($filter_models)
$dataProvider->setModels($filtered_models);
return $dataProvider;
}
I have a problem saving the data in the database . It saves them as 1970-01-01 , invalid date . I would read them as dd-mm-yyyy and convert them to the database in yyyy-mm-dd .
my model
public function behaviors()
{
return [
[
'class' => AttributeBehavior::className(),
'attributes' => [
attribute ['created','updated']
ActiveRecord::EVENT_BEFORE_INSERT => ['data_arrivo','data_part'],
ActiveRecord::EVENT_BEFORE_UPDATE => 'data_arrivo', 'data_part'
],
'value' => function ($event) {
return date('Y-m-d', strtotime($this->data_part));
},
],
];
Any suggestions?
You can use beforeSave event in model file. It will get call before saving the record into the table.
public function beforeSave($insert) {
if($this->data_part){
$this->data_part = Yii::$app->formatter->asDate(strtotime($this->data_part), "php:Y-m-d");
}
return parent::beforeSave($insert);
}
Don't work i post my code
public function beforeSave($insert) {
if($this->data_part){
$this->data_part = Yii::$app->formatter->asDatetime(strtotime($this->data_part), "php:Y-m-d");
if($this->data_arrivo)
$this->data_arrivo = Yii::$app->formatter->asDatetime(strtotime($this->data_arrivo), "php:Y-m-d");
}
return parent::beforeSave($insert);
}
I am trying to update some fields in yii 1.1 using the following rules, but it is not working.
public function rules()
{
return [
['CreatedOn','default','value'=>time(),'isEmpty'=>true,'on'=>'insert'],
['CreatedBy','default','value'=>\Yii::$app->user->identity->id,'isEmpty'=>true,'on'=>'insert'],
['ModifiedOn','default','value'=>time(),'isEmpty'=>true,'on'=>'update'],
['ModifiedBy','default','value'=>\Yii::$app->user->identity->id,'isEmpty'=>true,'on'=>'update'],
];
}
I am looking to update CreatedBy and CreatedOn when inserting, and ModifiedBy and ModifiedOn when updating.
From soju's excellent answer, with Yii2:
By default, a model supports only a single scenario named default
You should therefore set the scenario manually in your controller i.e:
$model->scenario = 'insert';
You could also use when instead of on i.e:
['CreatedOn', 'default', 'value'=>time(), 'isEmpty'=>true, 'when'=>
function($model) { return $model->isNewRecord; }
],
['ModifiedOn', 'default', 'value'=>time(), 'isEmpty'=>true, 'when'=>
function($model) { return !$model->isNewRecord; }
],
An alternative to setting them in rules() would be to use beforeSave() to set them:
public function beforeSave($insert) {
if ($insert) {
$this->CreatedBy = \Yii::$app->user->identity->id;
$this->CreatedOn = time();
} else {
$this->ModifiedBy = \Yii::$app->user->identity->id;
$this->ModifiedOn = time();
}
return parent::beforeSave($insert);
}
This is the correct way to do it:
Behaviors:
public function behaviors()
{
return [
'timestamp' => [
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'created_on',
ActiveRecord::EVENT_BEFORE_UPDATE => 'modified_on',
ActiveRecord::EVENT_BEFORE_DELETE => 'deleted_at',
],
'value' => function () {
return date('Y-m-d H:i:s');
}
],
[
'class' => BlameableBehavior::className(),
'createdByAttribute' => 'created_by_id',
'updatedByAttribute' => 'updated_by_id',
],
];
}
If you need just a simple rule for default value, this is enough:
public function rules()
{
return [
['CreatedOn','default','value'=>time()],
['ModifiedOn','default','value'=>time(),'isEmpty'=>true],
...
]
}
The 'isEmpty'=>true option override the default isEmpty() function and returns true (it is always seen as empty) dues it is always populated with time()
For Yii2 version 2.0.8 from April 2016 I had an error with 'isEmpty'=>true because according to documentation it expects a function so you must to do like this:'isEmpty' => function ($value) {return true;}.
When you use this solution you get a value for ModifiedBy even on create and I believe that was not an intention. It is possible to write isEmpty to return true in case of an update but I simply used 'when' because it is much more readable for me. So, my solution for rules in a model was :
['CreatedBy', 'default', 'value' => Yii::$app->user->id],
['ModifiedBy', 'default', 'value' => Yii::$app->user->id,
'when' => function ($model) { return !$model->isNewRecord;}],
As a side note for this question is that for timestamps you should rely on database to fill them, CreatedOn with default value and a before update trigger for ModifiedOn.
In view->new_entry.php
<?=form_open(base_url().'home/insert_entry/')?>
<p>Title: <?=form_input('title')?></p>
<p>Content: <?=form_textarea('content')?></p>
<p>Tags: <?=form_input('tags')?> (comma separated)</p>
<?=form_submit('submit', 'Insert')?>
In home/insert_entry:
public function insert_entry(){
login_site();
$entry = array(
'permalink' => permalink($this->input->post('title')),
'author' => $this->session->userdata('username'),
'title' => $this->input->post('title'),
'content' => $this->input->post('content'),
'date' => date('Y-m-d H:i:s'),
'tags' => $this->input->post('tags')
);
$this->home_model->insert('ads', $entry);
redirect(base_url());
}
In home_model:
public function insert($table, $data){
return $this->db->insert($table, $data);
}
I am getting all result zero (0) on database.
Try checking the affected_rows if it is >= 1
public function insert($table, $data){
$this->db->insert($table, $data);
return $this->db->affected_rows() >= 1 ? TRUE : FALSE;
}
Enable profiler in your controller.
eg:
$this->output->enable_profiler(TRUE);
See if your query is executed and if it's correct...