Just started with Yii (two weeks ago).
TL;DR
Creating through Gii generated views not working, but update does, even they share the form and controller not edited.
Problem:
I use the Yii2 advanced app template.
Then I generated a model through the model generator and controller/views through the CRUD generator.
The only thing I changed is removing the two datetime fields "created_at" and "created_by" from the form and added a TimestampBehavior:
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
// if you're using datetime instead of UNIX timestamp:
'value' => new Expression('NOW()'),
],
];
}
The strange case I have is, that the update is working, but the create not. It shows no error, it just stay on the page or renders it newly?
This is the untouched code from the controller:
(Am I getting it right that the "$model->save" in the if should save it to the databse?)
CREATE:
public function actionCreate()
{
$model = new Seminar();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
UPDATE:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
If further informations are needed please comment.
Thanks.
UPDATE - Solution
After the two helpful answers I tried dump the error and it shows
array(1) { ["created_at"]=> array(1) { [0]=> string(32) "Created At darf nicht leer sein." } }
As suggested I left the "created_at" in the "required" section of the rules. After cleaning it out the create works.
I think it did not show me the error because I deleted the field in the form, since the user should not enter data dirctly.
The Controllers you showed are ok.
There must be something wrong with the model. You can check what the problem is by editing the actionCreate:
public function actionCreate()
{
$model = new Seminar();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
var_dump($model->getErrors());
/*return $this->render('create', [
'model' => $model,
]);*/
}
}
Now, about your changes: since you are using the column names created_at and updated_at you can simplify the behavior by setting:
public function behaviors()
{
return [
TimestampBehavior::className()
];
};
Also, check your model rules() if the fields created_at or updated_at are there, and remove it. They are not needed anymore.
Check the rules in your model and try again. Also, try with $model->save(false). It will save the form without check validation, so the problem is that data doesn't validate.
Related
i'm still beginner in yii and php.
my problem is:
i want add a value that from db to my textfield.
my db table 'config' have 3 column, id;name;value;
i have tried code like this:
<?= $form->field($model, 'name')->textInput(['value'=>$model->value])->label('name',['class'=>'label-class'])?>
but it didn't show the value.
i want a update form for change value . example: name: title; value: hello world.
Your controller should be something like that:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
protected function findModel($id)
{
if (($model = Mymodel::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
and in view you simply write
<?= $form->field($model, 'name')->textInput()->label('name',['class'=>'label-class'])?>
Your database values will be in your field.
For simple CRUD you may use GII http://www.yiiframework.com/doc-2.0/guide-start-gii.html
I have a yii2 project, I am developing on my windows localhost and hosting remotely on linux.
Locally (windows) every thing is perfect.
While on linux, I have $model->id = null after $nodel->save(), although data is saved.
public function actionCreate() {
$model = new AppBreakingNews();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
I have tried die($model->id) after the save, it printed null.
Moreover, when I click on the update icon in the grid view, I am facing the same problem.
The AppBreakingNews is as follows:
<?php
namespace app\models\appmodels;
use app\models\BreakingNews;
use yii\behaviors\TimestampBehavior;
class AppBreakingNews extends BreakingNews {
public function behaviors() {
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => date('Y-m-d H:i:s'),
],
];
}
}
Notice that appBreakingNews extends the model BreakingNews that is generated by yii2 without any change.
Thanks in advance..
Please try to save model->save(false); because i think it validate something from model file.
public function actionCreate() {
$model = new AppBreakingNews();
if ($model->load(Yii::$app->request->post()) && $model->save(false)) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
or can you please print your model file here.
I try to save current user_id to the education table in database. However,the data of user_id is not filled. This is my code.
At model
public function rules()
{
return [
[['year', 'fieldstudy', 'institute', 'grade'], 'required'],
[['user_id'], 'integer'],
[['year', 'fieldstudy', 'institute', 'grade'], 'string', 'max' => 255],
];
}
public function attributeLabels()
{
return [
'education_id' => 'Education ID',
'user_id' => 'User ID',
'year' => 'Year',
'fieldstudy' => 'Fieldstudy',
'institute' => 'Institute',
'grade' => 'Grade',
];
}
public function getUser()
{
return $this->hasOne(User::className(), ['user_id' => 'user_id']);
}
At controller
public function actionCreate()
{
$model = new Education();
$model->user_id =Yii::$app->user->id;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->education_id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
How can I solve my problem and fix my code? Thanks
update Yii::$app->user->id to Yii::$app->user->identity->id.
public function actionCreate()
{
$model = new Education();
if ($model->load(Yii::$app->request->post())) {
$model->user_id =Yii::$app->user->identity->id;
if($model->save()){
return $this->redirect(['view', 'id' => $model->education_id]);
}
}
return $this->render('create', [
'model' => $model,
]);
}
You have to check two things
Check whether the user is logged in.
Use Yii2 debugger to see whether we are getting the id value of the logged in user by the code Yii::$app->user->id or Yii::$app->user->id
Use Yii2 debugger to check whether the correct user id value we are getting by using the code
Yii::info("User id=".Yii::$app->user->id);
Full code you have to try in the controller is given below
public function actionCreate() {
$model = new Education();
//checking whether we are getting the logged in user id value
Yii::info("User id=".Yii::$app->user->id);
$model->user_id = Yii::$app->user->id;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
//checking here the saved user id value in table
Yii::info("checking User id after saving model=".$model->user_id);
return $this->redirect(['view', 'id' => $model->education_id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
Now after running the application you can check using Yii2 debugger the values that are set in the user id in various places.
I'm doing a form where I enter the data in two models in a single form. My question is how to record data entry in actionCreate () and call these models in a single form.
These are my inscritoController.php
public function actionCreate()
{
$model = new Inscrito();
$modelEmpresa = new Empresa();
if ($model->load(Yii::$app->request->post()) && $model->load(Yii::$app->request->post()) && $modelEmpresa->save() && $modelEmpresa->save())
{
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'modelEmpresa' => $modelEmpresa,
]);
}
}
And Error:
PHP Notice – yii\base\ErrorException
Undefined variable: modelEmpresa
add this line in your controller
use app\models\Empresa;
Load Yii::$app->request->post() to $modelEmpresa and confirm model call in your controller use app\models\Empresa;
public function actionCreate()
{
$model = new Inscrito();
$modelEmpresa = new Empresa();
if ($model->load(Yii::$app->request->post()) && $modelEmpresa->load(Yii::$app->request->post()) && $model->save() && $modelEmpresa->save())
{
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'modelEmpresa' => $modelEmpresa,
]);
}
}
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.