can't solve 'date' validation with 'max', 'min' properties Yii2 - yii2

I can't understand - function returning string (verified by var_dump()):
['userBirthDate', 'date', 'format' => 'yyyy-MM-dd',
'max' => function() {
$date = new DateTime();
date_sub($date, date_interval_create_from_date_string('12 years'));
$maxDate = date_format($date, 'Y-m-d');
return $maxDate;
},
'min' => function() {
$date = new DateTime();
date_sub($date, date_interval_create_from_date_string('100 years'));
$minDate = date_format($date, 'Y-m-d');
return $minDate;
}
],
but I have the mistake:
"Object of class Closure could not be converted to string".

The validators max and min can only accept a number, not an anonymous function, that's why you are getting the error.
Try this code, which creates a new validator called validateUserBirthDate, as well as using the existing date validator.
[
['userBirthDate'],
'validateUserBirthDate'
],
[
['userBirthDate'],
'date', 'format' => 'format' => 'yyyy-MM-dd'
]
then in your model add a custom validator;
public function validateUserBirthDate($attribute, $params) {
$date = new \DateTime();
date_sub($date, date_interval_create_from_date_string('12 years'));
$minAgeDate = date_format($date, 'Y-m-d');
date_sub($date, date_interval_create_from_date_string('100 years'));
$maxAgeDate = date_format($date, 'Y-m-d');
if ($this->$attribute > $minAgeDate) {
$this->addError($attribute, 'Date is too small.');
} elseif ($this->$attribute < $maxAgeDate) {
$this->addError($attribute, 'Date is to big.');
}}

Related

I Keep Getting Invalid datetime format: 1292

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'
];
....
}

How to add new values to multiple Select2 from Kartik instead of replace old ones?

I use Select2 widget in multiply mode in YII2 framework. "kartik-v/yii2-widget-select2": "#dev" - this one I have downloaded via composer.
kartik-v/yii2-widget-select2 dev-master dd09e46
I added initial values with ajax on widget init ('initSelection'). And added another ajax method to suggest new values on user's typing. When user select one from list, it replaced initial values what were added on init. New values replace initial values, but don't another new.
I want new values to add to initial instead of replace it.
<?= $form->field($model, 'security[]')->widget(Select2::class, [
'attribute' => 'security',
'hideSearch' => true,
'data'=>$security_data,
'options' => [
'placeholder' => 'Security',
'multiple' => true,
],
'pluginOptions' => [
'allowClear' => true,
'minimumInputLength' => 1,
'ajax' => [
'url' => Url::toRoute([ '/admin/security/select-items' ]),
'dataType' => 'json',
'data' => new JsExpression('function(params) { return {q:params.term}; }'),
'results' => new JsExpression('function(data,page) { return {results:data.results}; }'),
],
'initSelection' => new JsExpression('function(element, callback) { var id = '.Yii::$app->request->getQueryParams()['id'].';if(id !== "") {$.ajax("' . \yii\helpers\Url::toRoute([ '/admin/security/init-items' ]) . '", {data: {id: id},dataType: "json"}).done(function(data) {callback(data.results);});}}'),
],
]); ?>
And here is my api methods:
public function actionSelectItems($q = null){
Yii::$app->response->format = Response::FORMAT_JSON;
$out = ['results' => []];
if(!empty($q)){
$items = Security::find()->where(['like', 'title', $q])->all();
foreach ($items as $item){
$out['results'][] = ['id'=>$item->id, 'text'=>$item->title];
}
}
return $out;
}
public function actionInitItems($id = null){
Yii::$app->response->format = Response::FORMAT_JSON;
$adv = Adv::findOne($id);
$security = #json_decode($adv->security, true);
$out = ['results' => []];
foreach ($security as $item){
$text = Security::findOne($item)->title;
$out['results'][] = ['id'=>$item, 'text'=>$text];
}
return $out;
}
Is there some sort of settings or I missed something when handle http result?

Checking existing record based on two fields

I am trying to insert some record by checking if certain conditions are met. What I am planning to do is to restrict the users from voting twice daily. I am using email and date as parameters.
public function store(Request $request)
{
$this->validate($request, [
'flavour' => 'required|string',
'email' => 'required|email',
'lastname'=> 'required|string',
'firstname' => 'required|string'
]);
$vote = new Vote();
//$currentDate = Carbon::now()->toDateString();
$today = Carbon::now()->format('Y-M-D');
$dup = Vote::where(['email' => $request->email, 'created_at' => $today ])->get();
if (!$dup)
{
$vote->firstname = $request->firstname;
$vote->lastname = $request->lastname;
$vote->email = $request->email;
$vote->flavour = $request->flavour;
$vote->voter_ip = $request->ip();
}
else {
return response()->json([
'message' => 'You have voted today, please wait till another day!'
]);
}
if (auth()->user()->votes()->save($vote))
return response()->json([
'success' => true,
'data' => $vote->toArray()
]);
else
return response()->json([
'success' => false,
'message' => 'Vote could not be added'
], 500);
}
The problem I am encountering now is, it doesn't take any record as it keeps displaying the message "You have voted today, please wait till another day", even if I insert a new email and/or a current user with different emails.
First, I had to create a field in my migration called "voted_at" and rearranged the code to check for the existing record based on the voted_at and email of the user
public function store(Request $request)
{
$this->validate($request, [
'flavour' => 'required|string',
'email' => 'required|email',
'lastname'=> 'required|string',
'firstname' => 'required|string'
]);
$today = Carbon::now()->toDateString();
$dup = Vote::where(['email' => $request->email, 'voted_at' => $today ])->exists();
if ($dup){
return response()->json([
'data' => $dup,
'message' => 'You have voted today, please wait till another day!'
]);
}
else {
$vote = new Vote();
$vote->firstname = $request->firstname;
$vote->lastname = $request->lastname;
$vote->email = $request->email;
$vote->flavour = $request->flavour;
$vote->voter_ip = $request->ip();
$vote->voted_at = $today;
if (auth()->user()->votes()->save($vote))
return response()->json([
'success' => true,
'data' => $vote->toArray()
]);
else
return response()->json([
'success' => false,
'message' => 'Vote could not be added'
], 500);
}
}
Thanks

Dropdown in list data

This is my code:
[
'attribute' => 'status',
'value' => function ($model) {
return Html::dropDownList('status', ['10' => 'Active', '20' => 'Deactive']);
},
],
I just want dropdown in status column. If record is active or deactive it will be selected.
You need to use 'format' => 'raw' for the column options and your definition for the dropDownList() is wrong you need to have the selection string as the second parameter and the dropdown options as the third parameter. Change your code to below:
[
'attribute' => 'status',
'format' => 'raw',
'value' => function ($model) {
return Html::dropDownList('status', $model->status, ['10' => 'Active', '20' => 'Deactive']);
},
],
EDIT
You didnt had in the initial requirements that you waned to update the status too when the drop down is changed. You can bind ajax call to the drop-down.
Add the following javascript on top of your view where you are initializing the GridView.
NOTE: Change the url:'controller/update-status?id'+id in the ajax call to the relative controller where you want to update the status for the row, but dont remove the id
$js = <<<JS
$(document).on('ready pjax:success',function(){
$(".switch-status").on('change',function(){
var data={};
data[$(this).attr("name")]=$(this).val();
var id=$(this).closest("tr").data('key');
$.ajax({
method:'post',
url:'/controller/update-status?id='+id,
data:data,
success:function(data){
if(!data.success){
alert(data.message);
}else{
alert("Status updated.");
}
},
error:function(jqXHR, textStatus, errorThrown ){
alert(errorThrown);
}
});
});
});
JS;
$this->registerJs($js, yii\web\View::POS_END);
Then inside your GridView column for status change the dropdown to the following
return Html::dropDownList(Html::getInputName($model, 'active'), $model->active, [10 => 'Active', 20 => 'Deactive'], ['class' => 'switch-status']);
And the go to your controller and add the action code for updating the status
Note: Change the Model in the first line $model = Model::findOne($id); name with the respective model you are using.
public function actionUpdateStatus($id) {
$model = Affiliate::findOne($id);
$app = Yii::$app;
$request = $app->request;
if($request->IsAjax && $request->isPost) {
Yii::$app->response->format = Response::FORMAT_JSON;
if($model->load($request->post()) && $model->save()) {
return ['success' => true];
} else {
return [
'success' => false,
'message' => implode('<br />', ArrayHelper::getColumn($model->errors, '0'))
];
}
}
}
Use content property to render HTML elements. For example:
[
'attribute' => 'status',
'content' => function ($model) {
return Html::dropDownList('status', $model->status, ['10' => 'Active', '20' => 'Deactive']);
},
],

cant import data csv to database in yii2

I am very new to web development.
I'm newbie in here, my first question in stackoverflow..
i am confused what error on code, Code will be store data array csv to a database,
sorry my bad english.
Controller
public function actionUpload()
{
$model = new Skt();
//error_reporting(E_ALL);
//ini_set('display_error', 1);
if ($model->load(Yii::$app->request->post())) {
$file = UploadedFile::getInstance($model, 'file');
$filename = 'Data.' . $file->extension;
$upload = $file->saveAs('uploads/' . $filename);
if ($upload) {
define('CSV_PATH', 'uploads/');
$csv_file = CSV_PATH . $filename;
$filecsv = file($csv_file);
foreach ($filecsv as $data) {
$modelnew = new Skt();
$hasil = explode(",", $data);
$no_surat= $hasil[0];
$posisi= $hasil[1];
$nama= $hasil[2];
$tgl_permanen= $hasil[3];
$grade= $hasil[4];
$tgl_surat= $hasil[5];
$from_date = $hasil[6];
$to_date = $hasil[7];
$modelnew->no_surat = $no_surat;
$modelnew->posisi = $posisi;
$modelnew->nama = $nama;
$modelnew->tgl_permanen = $tgl_permanen;
$modelnew->grade = $grade;
$modelnew->tgl_surat = $tgl_surat;
$modelnew->from_date = $from_date;
$modelnew->to_date = $to_date;
$modelnew->save();
//print_r($modelnew->validate());exit;
}
unlink('uploads/'.$filename);
return $this->redirect(['site/index']);
}
}else{
return $this->render('upload',['model'=>$model]);
}
return $this->redirect(['upload']);
}
Model
class Skt extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'skt';
}
public $file;
public function rules()
{
return [
[['file'], 'required'],
[['file'], 'file', 'extensions' => 'csv', 'maxSize' => 1024*1024*5],
[['no_surat'], 'required'],
[['tgl_surat', 'from_date', 'to_date'], 'string'],
[['no_surat', 'posisi', 'nama', 'tgl_permanen', 'grade'], 'string', 'max' => 255],
];
}
public function attributeLabels()
{
return [
'no_surat' => 'No Surat',
'posisi' => 'Posisi',
'nama' => 'Nama',
'tgl_permanen' => 'Tgl Permanen',
'grade' => 'Grade',
'tgl_surat' => 'Tgl Surat',
'from_date' => 'From Date',
'to_date' => 'To Date',
'file' => 'Select File'
];
}
}
thanks for helping..
change your code to the following to output the errors which could happen when you try to save. Errors could occur depending on your model rules.
if (!$modelnew->save()) {
var_dump($modelnew->getErrors());
}
getErrors() from Api
A better approach is to use exceptions to throw and catch errors on your import. Depends if you want to skip csv lines on errors or not.
finally it working with change this $hasil = explode(";", $data);