Yii2 call another action from my view - yii2

When i call my create action i got the followinf error :
Exception (Invalid Configuration) 'yii\base\InvalidConfigException' with message 'Invalid validation rule: a rule must specify both attribute names and validator type.'
That's my controllers' action:
public function actionCreate()
{
$model = new Message();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
And my rules function :
public function rules()
{
return [
[['sender_id', 'receiver_id', 'text'], 'required'],
[['sender_id', 'receiver_id', 'last_message', 'is_new', 'is_deleted_by_sender', 'is_deleted_by_receiver'], 'integer'],
[['created_at'], 'safe'],
[['text'], 'string', 'max' => 100],
[['receiver_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['receiver_id' => 'id']],
[['sender_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['sender_id' => 'id']],
[['admin/message/chat/idUser/<id:\d+>' => 'admin/message/chat']],
];
}

This
[['admin/message/chat/idUser/<id:\d+>' => 'admin/message/chat']],
is UrlManager rule, not validation rule - it should be in UrlManager configuration.

Related

yii2 ActiveData Provider

This is my user model
class User extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'user';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[[ 'created_at', 'updated_at', 'branch_id', 'postcode', 'tel_no', 'child_no','company_id'], 'integer'],
// [['branch_id', 'edu_level', 'date_joined','address1','country','state','city','postcode','race','position_level','religion','gender','staff_id','username','password','ic_number','tel_no','marital_status','child_no','bumi_status','resident_status','email','company_id'], 'required'],
[['get_mail', 'gender', 'marital_status', 'resident_status', 'bumi_status','designation','status'], 'string'],
[['date_joined'], 'safe'],
[['staff_id', 'password', 'edu_level', 'position_level', 'address2', 'address3', 'address4', 'country', 'state', 'city', 'race', 'religion'], 'string', 'max' => 100],
[['username', 'fullname', 'password_hash', 'password_reset_token', 'email', 'auth_key'], 'string', 'max' => 255],
[['ic_number'], 'string', 'max' => 14],
[['address1'], 'string', 'max' => 1000],
[['staff_id'], 'unique'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('user', 'ID'),
'staff_id' => Yii::t('user', 'Staff ID'),
'username' => Yii::t('user', 'Username'),
'fullname' => Yii::t('user', 'Fullname'),
'password' => Yii::t('user', 'Password'),
'password_hash' => Yii::t('user', 'Password Hash'),
'password_reset_token' => Yii::t('user', 'Password Reset Token'),
'email' => Yii::t('user', 'Email'),
'ic_number' => Yii::t('user', 'Ic Number'),
'auth_key' => Yii::t('user', 'Auth Key'),
'status' => Yii::t('user', 'Status'),
'created_at' => Yii::t('user', 'Created At'),
'updated_at' => Yii::t('user', 'Updated At'),
'company_id' => Yii::t('user', 'Company'),
'branch_id' => Yii::t('user', 'Branch'),
'edu_level' => Yii::t('user', 'Education Level'),
'position_level' => Yii::t('user', 'Position Level'),
'designation' => Yii::t('user', 'Designation'),
'get_mail' => Yii::t('user', 'Get Mail'),
'date_joined' => Yii::t('user', 'Date Joined'),
'gender' => Yii::t('user', 'Gender'),
'address1' => Yii::t('user', 'Address1'),
'address2' => Yii::t('user', 'Address2'),
'address3' => Yii::t('user', 'Address3'),
'address4' => Yii::t('user', 'Address4'),
'country' => Yii::t('user', 'Country'),
'state' => Yii::t('user', 'State'),
'city' => Yii::t('user', 'City'),
'postcode' => Yii::t('user', 'Postcode'),
'tel_no' => Yii::t('user', 'Tel No'),
'marital_status' => Yii::t('user', 'Marital Status'),
'child_no' => Yii::t('user', 'Child No'),
'race' => Yii::t('user', 'Race'),
'religion' => Yii::t('user', 'Religion'),
'resident_status' => Yii::t('user', 'Resident Status'),
'bumi_status' => Yii::t('user', 'Bumi Status'),
];
}
public static function find()
{
return new UserQuery(get_called_class());
}
public function getCountries()
{
return $this->hasOne(Countries::classname(),['id'=>'country']);
}
public function getStates()
{
return $this->hasOne(States::classname(),['id'=>'state']);
}
public function getNext_of_kin()
{
return $this->hasMany(NextOfKin::classname(),['staff_id'=>'staff_id']);
}
}
This is my view controller
public function actionView($staff_id)
{
$request = Yii::$app->request;
$model = $this->findModel($staff_id);
$model2 = $model ->next_of_kin;
//$sql = "SELECT next_of_kin.name AS Name FROM user left join next_of_kin ON next_of_kin.staff_id = user.staff_id";
$dataProvider = new ActiveDataProvider([
'query' => User::find() ->joinWith(['next_of_kin'])-> where(['next_of_kin.staff_id' => $staff_id]),
]);
if($request->isAjax)
{
Yii::$app->response->format = Response::FORMAT_JSON;
return [
'title'=> "User #".$staff_id,
'content'=>$this->renderAjax('view', [
'model' => $model,
'dataProvider' => $dataProvider,
]),
'footer'=> Html::button('Close',['class'=>'btn btn-default pull-left','data-dismiss'=>"modal"]).
Html::a('Edit',['update','staff_id'=>$staff_id],['class'=>'btn btn-primary','role'=>'modal-remote'])
];
}
else
{
return $this->render('view', [
'model' => $model,
'dataProvider' => $dataProvider,
"size" => "modal-lg",
]);
}
}
This is the view file
[
'label' => 'Next of Kin Details',
'content' => GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'username',
'fullname',
'staff_id',
'next_of_kin.name',
],
]),
],
I trying to get the name from table next_of_kin based on the staff id inside the User table. But it keep show not set when I try to view it
Why use array when you want to join with a single table/relation, I mean it shouldn't be wrong, but it's confusing.
Your query doesn't seem wrong, look for the Database module of the debugger to see what the actual query Yii AR composed and run it in the DB in a raw form. The query itself is not broken, at least from what I can tell, DB architecture, the fact that you can query for a staff_id that has nothing to return, the way you pass $staff_id and several other stuff could be broken.
activeDataProvider return a collection of models
you can retrieve an array of model from dataProvider
$myModels = $dataProvider->getModels();
eg: get the first element(user model) next_of_kin models
$my_next_of_kin = $myModels[0]->next_of_kin;
iterate over models for get a value;
foreach ($my_next_of_kin as $key => $value) {
echo $value->your_next_of_kin_col;
}
It works only with one-to-one relations! You have one-to-many.
public function getNext_of_kin()
{
return $this->hasMany(NextOfKin::classname(),['staff_id'=>'staff_id']);
}
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'username',
'fullname',
'staff_id',
'next_of_kin.name', // "next_of_kin" should be one-to-one relation
],

Call to a member function saveAs() on null (I can not update if I do not select an image)

I can not update if I do not select an image. What do wrong or I'm missing?
This is a controller:
if ($model->load(Yii::$app->request->post())) {
$nameImage=$model->name;
$model->bookimg=UploadedFile::getInstance($model,'bookimg');
$model->bookimg->saveAs('images/'.$nameImage.'.'.$model->bookimg->extension);
$model->bookimg='images/'.$nameImage.'.'.$model->bookimg->extension;
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
This is a model:
[['fkperiodo'], 'integer'],
[['date_public'], 'safe'],
[['name'], 'string', 'max' => 100],
[['volume'], 'string', 'max' => 5],
[['author',], 'string', 'max' => 255],
[['bookimg'], 'file', 'skipOnEmpty' => true, 'extensions' => 'png, jpg'],
[['fkperiod'], 'exist', 'skipOnError' => true, 'targetClass' => Period::className(), 'targetAttribute' => ['fkperiod' => 'id']],
This is a form:
<?= $form->field($model, 'bookimg')->fileInput()->label('Book Cover') ?>
You have to check if $model to be updated had already an image and react accordingly if user has chosen a new image.
Example
if ($model->load(Yii::$app->request->post())) {
$nameImage = $model->name;
$old_image = $model->bookimg;
$model->bookimg = UploadedFile::getInstance($model, 'bookimg');
//If user has chosen an image
if (!empty($model->bookimg)) {
if (!empty($old_image)) {
//Delete old image from filesystem or/and database
//...
//...
}
//Save the new image
$model->bookimg->saveAs('images/'.$nameImage.'.'.$model->bookimg->extension);
$model->bookimg = 'images/'.$nameImage.'.'.$model->bookimg->extension;
}
//Also consider checking if model has been successfully saved before redirect
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}

Yii2 save in the table user_id account

I'm a beginner in yii2 , I would like to save in the table associated with the account , the account id . Any suggestions?
My Model
class Offri extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'viaggio';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['citta_part','citta_arrivo','user_id'], 'required'],
[['data_part','ora_part','data_arrivo','ora_arrivo'],'safe'],
[['posti_disponibili', 'conferma_utenze', 'user_id','posti_max'], 'integer'],
[['prezzo'], 'number'],
[['citta_part', 'via_part', 'citta_arrivo', 'via_arrivo', 'veicolo'], 'string', 'max' => 45],
[['note'], 'string', 'max' => 255],
[['wifi', 'bagno', 'ac_dc','condizioni'],'integer'],
[['user_id'], 'unique'],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id_viaggio' => Yii::t('app', 'Id Viaggio'),
'citta_part' => Yii::t('app', 'Citta Part'),
'via_part' => Yii::t('app', 'Via Part'),
'ora_part' => Yii::t('app', 'Ora Part'),
'data_part' => Yii::t('app', 'Data Part'),
'posti_disponibili' => Yii::t('app', 'Posti Disponibili'),
'conferma_utenze' => Yii::t('app', 'Conferma Utenze'),
'prezzo' => Yii::t('app', 'Prezzo'),
'note' => Yii::t('app', 'Note'),
'citta_arrivo' => Yii::t('app', 'Citta Arrivo'),
'data_arrivo' => Yii::t('app', 'Data Arrivo'),
'ora_arrivo' => Yii::t('app', 'Ora Arrivo'),
'via_arrivo' => Yii::t('app', 'Via Arrivo'),
'veicolo' => Yii::t('app', 'Veicolo'),
'posti_max' => Yii::t('app', 'Posti Max'),
'wifi' => Yii::t('app', 'Wifi'),
'bagno' => Yii::t('app', 'Bagno'),
'ac_dc' => Yii::t('app', 'Ac Dc'),
];
}
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id'])->inverseOf('offri');
}
the field that I want to save in the table is user_id , which must be to the account id
My Controller
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use app\filters\AccessRule;
use yii\filters\VerbFilter;
use app\models\LoginForm;
use app\models\ContactForm;
use app\models\Accounts;
use app\models\Offri;
class SiteController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout'],
'rules' => [
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['#'],
],
[
'actions' => ['create'],
'allow' => true,
'roles' => ['admin'],
],
[
'actions' => ['view', 'search'],
'allow' => true,
'roles' => ['?', '#', 'admin'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
/**
* #inheritdoc
*/
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
public function actionregisterUser()
{
$model = new Accounts();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->registerUser()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
}
public function actionSomeAction($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => (string) $model->_id]);
}elseif (Yii::$app->request->isAjax) {
return $this->renderAjax('_form', [
'model' => $model
]);
} else {
return $this->render('_form', [
'model' => $model
]);
}
}
public function actionOffri()
{
$model = new Offri;
if($model->load(Yii::$app->request->post())&& $model->validate() && $model->save())
{
Yii::$app->session->setFlash('success', 'Hai inserito i dati correttamente');
return $this->render('offri', ['model' => $model]);
}else {
Yii::$app->getSession()->setFlash('error', 'Completa correttamente tutti i campi.');
return $this->render('offri', ['model' => $model]);
}
}
}
update your actionOffri() like below
public function actionOffri()
{
$model = new Offri;
if($model->load(Yii::$app->request->post())){
$model->user_id=Yii::$app->user->identity->id;
if($model->validate() && $model->save()){
Yii::$app->session->setFlash('success', 'Hai inserito i dati correttamente');
return $this->render('offri', ['model' => $model]);
}else {
Yii::$app->getSession()->setFlash('error', 'Completa correttamente tutti i campi.');
return $this->render('offri', ['model' => $model]);
}
}
work my Controller
public function actionOffri()
{
$model = new Offri;
$model->user_id = Yii::$app->user->identity->id;
if($model->load(Yii::$app->request->post())&& $model->validate() && $model->save())
{
Yii::$app->session->setFlash('success', 'Hai inserito i dati correttamente');
return $this->render('offri', ['model' => $model]);
}else {
Yii::$app->getSession()->setFlash('error', 'Completa correttamente tutti i campi.');
return $this->render('offri', ['model' => $model]);
}
}
work my model
public function rules()
{
return [
[['citta_part','citta_arrivo'], 'required'],
[['data_part','ora_part','data_arrivo','ora_arrivo'],'safe'],
[['posti_disponibili', 'conferma_utenze','posti_max'], 'integer'],
[['prezzo'], 'number'],
[['citta_part', 'via_part', 'citta_arrivo', 'via_arrivo', 'veicolo'], 'string', 'max' => 45],
[['note'], 'string', 'max' => 255],
[['wifi', 'bagno', 'ac_dc','condizioni'],'integer'],
];
}
i have removed in rules 'user_id'

CakePHP 3 hasMany will not pass parent ID to associated children

/* ShootsTable.php Meta Table */
public function initialize(array $config)
{
$this->table('shoots');
$this->displayField('title');
$this->primaryKey('id');
$this->hasMany('ShootMeta');
}
/* ShootMetaTable.php Meta Table */
public function initialize(array $config)
{
$this->table('shoot_meta');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Shoots');
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['shoots_id'], 'Shoots'));
return $rules;
}
/* Shoots.php Controller */
public function add()
{
$shoot = $this->Shoots->newEntity(null);
if ($this->request->is('post')) {
$this->Shoots->patchEntity($shoot, $this->request->data,[
'associated' => ['ShootMeta']
]);
$shoot->set('created_by', 1);
debug($shoot);
if ($this->Shoots->save($shoot,['associated' => ['ShootMeta']])) {
$this->Flash->success('The shoot has been saved.');
// return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The shoot could not be saved. Please, try again.');
}
}
$this->set(compact('shoot'));
$this->set('_serialize', ['shoot']);
}
/* Add.ctp Template */
<div class="shoots form large-10 medium-9 columns">
<?= $this->Form->create($shoot); ?>
<fieldset>
<legend><?= __('Add Shoot') ?></legend>
<?php
echo $this->Form->input('title');
echo $this->Form->input('content');
echo $this->Form->input('datetime', ['label' => 'Date/Time Of Shoot']);
echo $this->Form->input('shoot_meta.0.meta_key', ['type' => 'hidden', 'value' => 'photographer_spaces']);
echo $this->Form->input('shoot_meta.0.meta_value',['label' => 'Photographer Spaces', 'type' => 'number']);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
/* debug($shoots) output */
object(App\Model\Entity\Shoot) {
'new' => true,
'accessible' => [
'created_by' => true,
'title' => true,
'content' => true,
'datetime' => true,
'shoot_meta' => true
],
'properties' => [
'title' => '123',
'content' => '123',
'datetime' => object(Cake\I18n\Time) {
'time' => '2015-03-19T07:04:00+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'shoot_meta' => [
(int) 0 => object(App\Model\Entity\ShootMetum) {
'new' => true,
'accessible' => [
'shoots_id' => true,
'meta_key' => true,
'meta_value' => true,
'shoot' => true
],
'properties' => [
'meta_key' => 'photographer_spaces',
'meta_value' => '123'
],
'dirty' => [
'meta_key' => true,
'meta_value' => true
],
'original' => [],
'virtual' => [],
'errors' => [
'shoots_id' => [
'_required' => 'This field is required'
]
],
'repository' => 'ShootMeta'
}
],
'created_by' => (int) 1
],
'dirty' => [
'title' => true,
'content' => true,
'datetime' => true,
'shoot_meta' => true,
'created_by' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Shoots'
}
As you can see, the field shoots_id is required, which I would have thought would be automatically passed down (although at this point it hasn't executed any MySQL).
I feel I may have gone about this the wrong way but have spent 2 full days trying to get it right. One of those days was me trying to work out why after baking it had named a lot of the references to ShootMeta to ShootMetum, I thought it had actually corrupted it.
One of the biggest issues I have is knowing where to use shoot_meta, ShootMeta, shootmeta, shootmetum, ShootMetum etc. It feels like a bit of a minefield!
/Update
A dump of the save object below. It is clearly assigning it, it just seems to not be executing it in the SQL?
'shoot_meta' => [
(int) 0 => object(App\Model\Entity\ShootMetum) {
'new' => false,
'accessible' => [
'shoots_id' => true,
'meta_key' => true,
'meta_value' => true
],
'properties' => [
'meta_key' => 'photographer_spaces',
'meta_value' => '123',
'shoot_id' => '2',
'id' => '3'
],
'dirty' => [],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'ShootMeta'
},
Found it.
It is referring to shoot_id when i debug the save
'shoot_meta' => [
(int) 0 => object(App\Model\Entity\ShootMetum) {
'new' => false,
'accessible' => [
'shoots_id' => true,
'meta_key' => true,
'meta_value' => true
],
'properties' => [
'meta_key' => 'photographer_spaces',
'meta_value' => '123',
'shoot_id' => '2',
'id' => '3'
],
'dirty' => [],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'ShootMeta'
},
for some reason it was using the singular name for the association. Changed in the Shoots.php model.
From
$this->hasMany('ShootMeta');
To
$this->hasMany('ShootMeta',[
'foreignKey' => 'shoots_id'
]);
Remove the validation rule for shoots_id. Validation is for data that is posted from the form, and in this case the foreignKey cannot be posted from the Form. You already have rules in your buildRules() method for making sure that value is passed before saving, so removing the validation is 100% safe.
i have same problem like this to, for now my solution is sending associated data to other function/methode and save it.
eg
**
public function add() {
$kantor = $this->Kantor->newEntity($this->request->data);
if ($this->request->is('post')) {
$kantor = $this->Kantor->patchEntity($kantor, $this->request->data);
$rgndata = $this->request->data['Telpkantor'];
$this->request->session()->write('rgndata', $rgndata);
if ($this->Kantor->save($kantor)) {
$result = $this->Kantor->save($kantor);
$this->addTelpKantor($rgndata, $result->id);
$this->Flash->success('The kantor has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The kantor could not be saved. Please, try again.');
}
}
$reffKota = $this->Kantor->ReffKota->find('list', ['limit' => 200]);
$statusKantor = $this->Kantor->StatusKantor->find('list', ['limit' => 200]);
$pimpinan = $this->Kantor->Pimpinan->find('list', ['limit' => 200]);
$jenisTelp = $this->Kantor->Telpkantor->Jenistelp->find('list', ['limit' => 200]);
$this->set(compact('kantor', 'reffKota', 'statusKantor', 'pimpinan', 'jenisTelp'));
$this->set('_serialize', ['kantor']);
}
public function addTelpKantor($rgndata = null, $kantor_id=null) {
if (!empty($rgndata[0]['noTelp'])) {
$this->loadModel('Telpkantor');
foreach ($rgndata as $rgndata) {
$rgndata['kantor_id'] =$kantor_id;
$rgndatasave = $this->Telpkantor->newEntity($rgndata);
$this->Telpkantor->save($rgndatasave);
}
}
}
**

Validation error message is not shown when using listBox in ActiveField

I have a piece of the following code:
form->field($website, 'clients_id', [
'template' => "{label}<div class='col-md-9'>{input}</div>\n{hint}\n{error}"
])
->listBox($dataList, [
'data-placeholder' =>'Choose one..',
'class' => 'select-select2',
'style' => 'width: 100%',
'id' => 'example-select2'
])
->label('Clients')
In website model still return error validation for "clients_id" field. but in view not show the error
Although in the develop tool I still see this tag
<div class="help-block help-block-error "></div>
--- UPDATE ---
in my model :
public function rules()
{
return [
[['domain', 'clients_id', 'online_date'], 'required'],
[['online_date', 'created_at', 'updated_at'], 'safe'],
[['active', 'clients_id'], 'integer'],
[['domain'], 'string', 'max' => 255]
];
}
and when I print error validations
array(1) {["clients_id"]=> array(1) {[0]=> string(27) "Clients ID cannot be blank." }}
-- ActiveForm settings in view ---
<?php
$form = ActiveForm::begin([
'id' => 'web-form',
'layout' => 'horizontal',
'options' => [
'class' => 'form-horizontal form-bordered',
'enctype' => 'multipart/form-data'
],
'fieldConfig' => [
'horizontalCssClasses' => [
'label' => 'col-md-3 control-label',
],
],
]);
?>
Thanks