I can't insert data in the database. I'm using yii2 advanced.
I have 3 tables: the default user table, post, and category. Each post has one category, and one category can have many posts.
But when I click on 'Save' in my create form - nothing happens, the page just refreshes. The post table is still empty.
Here's PostController
namespace frontend\controllers;
use Yii;
use yii\web\Controller;
use frontend\models\CreateForm;
use frontend\models\Category;
use yii\helpers\ArrayHelper;
class PostController extends Controller
{
public function actionCreate()
{
if(Yii::$app->user->isGuest)
{
return $this->redirect(['/site/login']);
}
$model = new CreateForm();
$category = Category::find()->all();
$items = ArrayHelper::map($category, 'id', 'name');
if ($model->load(Yii::$app->request->post()))
{
if ($model->save())
{
Yii::$app->session->setFlash(
'success',
true
);
return $this->refresh();
} else
{
Yii::$app->session->setFlash(
'success',
false
);
}
}
return $this->render('create', [
'model' => $model,
'items' => $items
]);
}
This is CreateForm model
namespace frontend\models;
use yii\base\Model;
use frontend\models\Post;
use Yii;
class CreateForm extends Model
{
public $category;
public $title;
public $content;
public function attributeLabels()
{
return [
'category' => 'Category',
'title' => 'Title',
'content' => 'Content',
];
}
public function save()
{
$post = new Post();
$post->user_id = Yii::$app->user->id;
$post->category_id = $this->category;
$post->title = $this->title;
$post->content = $this->content;
$post->created_at = time();
}
}
And this the view
use yii\bootstrap\ActiveForm;
use yii\bootstrap\Html;
$form = ActiveForm::begin();
echo $form->field($model, 'category')->dropDownList($items);
echo $form->field($model, 'title')->textInput();
echo $form->field($model, 'content')->textInput();
echo Html::submitButton('Save', ['class' => 'btn btn-primary']);
ActiveForm::end();
What am I doing wrong, I can't understand
Ok. All I had to do is to add $post->save() in the end of my save method in CreateForm.
Related
When I try to upload multiple files, I can't do this
Model File:
namespace app\models;
class ImageFiles extends \yii\base\Model
{
public $imageFiles;
public function rules()
{
return [[
['imageFiles'],
'file',
'skipOnEmpty'=>false,
'extensions'=>'jpg, png',
'maxFiles'=>4
]];
}
}
View File
use yii\widgets\ActiveForm;
$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]);
echo $form->field($model, 'imageFiles[]')->fileInput(['multiple'=>true, 'accept'=>'image/*']);
echo \yii\helpers\Html::submitButton('Submit',['class'=>'btn btn-success']);
ActiveForm::end();
Controller File
namespace app\controllers;
use Yii;
class ImageFilesController extends \yii\web\Controller
{
public function actionIndex()
{
$model = new \app\models\ImageFiles();
if(Yii::$app->request->isPost){
$model->imageFiles = \yii\web\UploadedFile::getInstance($model, 'imageFiles');
print_r($model->imageFiles);
return;
}
return $this->render('index', ['model'=>$model]);
}
}
print_r($model->imageFiles) show me nothing and no errors, because $model->imageFiles has no value. but when I use print_r($_FILES) It prints all images details. I got confused I did what the Yii documentation said but it is not working.
For multiple files use UploadedFile::getInstances()
class ImageFilesController extends \yii\web\Controller
{
public function actionIndex()
{
$model = new \app\models\ImageFiles();
if(Yii::$app->request->isPost){
$model->imageFiles = \yii\web\UploadedFile::getInstances($model, 'imageFiles');
print_r($model->imageFiles);
return;
}
return $this->render('index', ['model'=>$model]);
}
}
I'm getting a undefined variable error in my view if I include this route with a parameter:
<div class="table-toolbar">
<div class="row">
<div class="col-md-6">
<div class="btn-group">
<i class="fa fa-plus"></i> Add new
</div>
</div>
</div>
</div>
Here's my full controller for that given view:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Model\CampusMajor;
use App\Model\CampusMajorsFacilities;
class CampusMajorsFacilitiesController extends Controller
{
//
public function index($campusMajorId)
{
$campusMajorsFacilities = CampusMajorsFacilities::ofCampusMajor($campusMajorId)->get();
$data = [
'campusMajorsFacilities' => $campusMajorsFacilities,
'campusMajor' => $campusMajorId
];
return view('major-facilities.index', $data);
}
public function add($campusMajorId)
{
$campusMajorsFacilities = new CampusMajorsFacilities;
$data = [
'campusMajorsFacilities' => $campusMajorsFacilities,
'campusMajorId' => $campusMajorId,
'formIs' => 'add'
];
return view('major-facilities.form', $data);
}
public function save(Request $request,$campusMajorId)
{
$this->validation($request);
$post = $request->all();
$campusMajorsFacilities = $this->bindToObject($post,$campusMajorId);
$campusMajorsFacilities->save();
return redirect()->route('major-facilities.index', $campusMajorId)->with('message','Item added Succesfully');
}
public function edit($campusMajorId, $id)
{
$campusMajorsFacilities = CampusMajorsFacilities::find($id);
$data = [
'campusMajorsFacilities' => $campusMajorsFacilities,
'campusMajorId' => $campusMajorId,
'formIs' => 'edit'
];
return view('major-facilities.form', $data);
}
public function update(Request $request,$campusMajorId,$id)
{
$this->validation($request);
$post = $request->all();
$campusMajorsFacilities = $this->bindToObject($post,$campusMajorId,$id);
$campusMajorsFacilities->save();
return redirect()->route('major-facilities.index', $campusMajorId)->with('message','Item updated Succesfully');
}
private function validation($request)
{
$this->validate($request,[
'title' => 'required',
'description' => 'required',
'content' => 'required',
'campus_major_id' => 'required'
]);
}
public function delete($campusMajorId,$id)
{
$campusMajorsFacilities = CampusMajorsFacilities::find($id);
$campusMajorsFacilities->delete();
return redirect()->route('major-facilities.index', $campusMajorId)->with('message','Item deleted Succesfully');
}
private function bindToObject($post,$campusMajorId,$id=null)
{
if(is_null($id)){
$campusMajorsFacilities = new CampusMajorsFacilities;
} else {
$campusMajorsFacilities = CampusMajorsFacilities::find($id);
}
$campusMajorsFacilities->major_campus_id = $campusMajorId;
$campusMajorsFacilities->title = $post['title'];
$campusMajorsFacilities->description = $post['description'];
$campusMajorsFacilities->content = $post['content'];
return $campusMajorsFacilities;
}
}
And my model
<?php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class CampusMajorsFacilities extends Model
{
//
use SoftDeletes;
public function CampusMajor()
{
return $this->belongsTo('App\Model\CampusMajor');
}
public function scopeOfCampus($query, $campus_id)
{
return $query->where('campus_id', $campus_id);
}
public function scopeOfCampusMajor($query, $campus_major_id)
{
return $query->where('campus_major_id', $campus_major_id);
}
}
If I comment out the route I passed the view just fine, I don't know where I went wrong.
You have passed $campusMajorId from controller to view as campusMajor only, not as campusMajorId.
Hence the variable is undefined in the view.
I'm new to Yii2. I've three tables project, amenity and a junction table project_amenity, and here is the code:
Project Model:
<?php
namespace app\models;
use yii\db\ActiveRecord;
class Project extends \yii\db\ActiveRecord
{
public function getAmenities()
{
return $this->hasMany(Amenity::className(), ['id' => 'amenity_id'])->viaTable('project_amenity', ['project_id' => 'id']);
}
public function rules()
{
return [
[['name', 'city'], 'required'],
];
}
}
Amenity Model:
<?php
namespace app\models;
use yii\db\ActiveRecord;
class Amenity extends \yii\db\ActiveRecord
{
public function getProjects()
{
return $this->hasMany(Project::className(), ['id' => 'project_id'])->viaTable('project_amenity', ['amenity_id' => 'id']);
}
}
ProjectController:
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use app\models\Project;
use app\models\Amenity;
use yii\helpers\ArrayHelper;
class ProjectController extends Controller
{
public function actionCreate()
{
$project = new Project;
$amenities = ArrayHelper::map(Amenity::find()->all(), 'id', 'name');
if ($project->load(Yii::$app->request->post()) && $project->save()) {
return $this->render(['confirm', 'id' => $project->id]);
} else {
return $this->render('create', [
'project' => $project, 'amenities' => $amenities
]);
}
}
}
And here is the Incomplete create view:
<?php
use yii\helpers\Html;
use yii\widgets\LinkPager;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>
<table class="table">
<tr>
<td><?= $form->field($project, 'name'); ?></td>
</tr>
<tr>
<td ><?= $form->field($project, 'city'); ?></td>
</tr>
<tr>
<td><?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?></td>
</tr>
</table>
<?php ActiveForm::end(); ?>
ProjectAmenity Junction Model
<?php
namespace app\models;
use yii\db\ActiveRecord;
class ProjectAmenity extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'project_amenity';
}
public function rules()
{
return [
[['project_id', 'amenity_id'], 'required']
];
}
}
?>
I'am able to display the relational data but not able to insert. Please suggest how to display the amenity checkboxes on create view and and how to insert the data in project and project_amenity table from the create view.
Add amenities property to your project model:
public $amenities;
Add a checkboxlist to your view:
<?= $form->field($project, 'amenities')->checkboxList($amenities) ?>
Create junction model if not already exists.
Loop through input in create action after save:
if ($project->load(Yii::$app->request->post()) && $project->save()) {
// checkboxlist fills amenities property with corresponding keys
foreach($project->amenities as $amenity_key) {
$project_amenity = new ProjectAmenity([
'project_id' => $project->id,
'amenity_id' => $amenity_key
]);
$project_amenity->save();
}
}
<?= $form->field($project, 'amenities')->inline()->checkBoxList(
ArrayHelper::map(Amenity ::find()->all(), 'name', 'name'),
['style'=>'width:500px']
)
?>
I have these classes:
Model:
namespace app\models;
use \yii\db\ActiveRecord;
class MyModel extends ActiveRecord {
public function rules() {
return [
[['name'], 'required'],
[['id'], 'default', 'value' => null]
];
}
}
Controller:
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\MyModel;
class MymodelController extends Controller{
public function actionEdit($id = null){
$model = new MyModel();
if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->save()) {
Yii::$app->session->setFlash('msg', 'Model has been saved with ID ' . $model->id);
}
return $this->render('edit', [
'model' => $model
]);
}
}
View:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php if(Yii::$app->session->hasFlash('msg')): ?>
<div class="alert alert-success"><?= Yii::$app->session->getFlash('msg'); ?></div>
<?php endif; ?>
<?php $form = ActiveForm::begin(); ?>
<?= Html::activeHiddenInput($model, 'id'); ?>
<?= $form->field($model, 'name') ?>
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
I want to use this view for editing and for inserting. Editing does not work as it is, because I am creating a new object instead of changing an existing one in the Controller. I am unsure what is the best practice here or if I am missing some already existing built in function?
Should I create my own model class and implement the logic model <-> active record in the controller
or
Should I just re query the database with the $model->id in the controller and copy all properties if needed?
you should use two actions for edit and insertion
for edit first find the model
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('edit', [
'model' => $model,
]);
}
protected function findModel($id)
{
if (($model = MyModel::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
if you use CRUD for generating your controller you don't have to write these actions.
For CRUD (Create, Read/View, Update and delete) you can use gii. This power tool generate automatically all you need for an ActiveRecord, Controller with the basic action (index, view, create, update, delete, find) and related view.
In gii you first genearate model class and then generate CRUD for this class.
But the most informant things all this information are coerently related each other
see this doc is very useful and the best pratice for Yii2 is embetted in the tool
http://www.yiiframework.com/doc-2.0/guide-start-gii.html
In Your Create action:
public function actionCreate()
{
$model = new Yourmodel();
if ($model->load(Yii::$app->request->post())) {
if($model->save()){
return $this->redirect(['view']);
}
}
return $this->render('create', [
'model' => $model,
]);
}
In your Update action:
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
if($model->save()){
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('update', [
'model' => $model,
]);
}
What I meet is almost like this:
I have a create form, and the form contains two model's attribute;
I pass them from controller to view, and add rules to validate attribute in both model;
But the form validation did not work well - a model's validation is
not work.
I have no idea about how to resolve this, thanks for help!
And I find a reference article - Complex Forms with Multiple Models, but it is TBD.
Here is my sample code.
Controller - SiteController.php:
namespace task\controllers;
use yii\web\Controller;
use task\models\Task;
use task\models\Customer;
class Task extends Controller
{
public function actionCreate()
{
$model = new Task;
$customerModel = new Customer;
// load, validate, save ...
return $this->render('create', [
'model' => $model,
'customerModel' => $customerModel
]);
}
}
Model - Task.php, Customer.php:
namespace task\models;
use yii\db\ActiveRecord;
class Task extends AcitveRecord
{
public $title, $published_at;
public function rules()
{
return [
[['title', 'published_at'], 'required'],
['published_at', 'match', 'pattern' => '/patten for time/']
];
}
}
namespace task\models;
use yii\db\ActiveRecord;
class Customer extends ActiveRecord
{
public $name;
public function rules()
{
return [
['name', 'required'],
];
}
}
View - create.php:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'title')->textInput() ?>
<?= $form->field($model, 'publish_at')->textInput() ?>
<?= $form->field($customerModel, 'name')->textInput() ?>
<?= Html::submitButton('submit')?>
<?php ActiveForm::end(); ?>
This can be an option. You can try it by creating an custom model, like ContactForm something like this:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
/**
* CustomModel is the model behind the contact form.
*/
class CustomModel extends Model
{
public $attributeFromModel1;
public $attributeFromModel2;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
// attributeFromModel1, attributeFromModel2 are required
[['attributeFromModel1', 'attributeFromModel2'], 'required'],
// ['email', 'email'],
['attributeFromModel1','YourRule']
// verifyCode needs to be entered correctly
['verifyCode', 'captcha'],
];
}
/**
* #return array customized attribute labels
*/
public function attributeLabels()
{
return [
'atttributeFromModel1' => 'Your Label',
'atttributeFromModel2' => 'Your Label ',
];
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
$customerModel = Customer::findOne($id);
if (!isset($model, $customerModel)) {
throw new NotFoundHttpException("The user was not found.");
}
$model->scenario = 'update';
$customerModel->scenario = 'update';
if ($model->load(Yii::$app->request->post()) && $customerModel->load(Yii::$app->request->post())) {
$isValid = $model->validate();
$isValid = $customerModel->validate() && $isValid;
if ($isValid) {
$model->save(false);
$customerModel->save(false);
return $this->redirect(['view', 'id' => $id]);
}
}
return $this->render('update', [
'model' => $model,
'customerModel' => $customerModel,
]);
}