Yii 2.0 - Input values saved as null in database - php

In my practice app, I have a table called 'music' with 3 columns - id, title and artist. Whenever I try to insert the input values from the form to the database, a new record is added but only id has a value, title and artist are both null. Below is my model:
<?php namespace app\models;
/**
* This is the model class for table "music".
*
* #property integer $id
* #property string $title
* #property string $artist
*/
class MusicEntry extends \yii\db\ActiveRecord {
public $title;
public $artist;
public $id;
public static function tableName() {
return 'music';
}
public function rules() {
return [
[['title', 'artist'], 'required'],
[['id'], 'safe'],
];
}
} ?>
While my controller action looks like so:
public function actionMusicEntry() {
$model = new MusicEntry ();
if (isset ( $_POST ['MusicEntry'] )) {
$model->load($_POST);
if ($model->save()) {
Yii::$app->session->setFlash ( 'success', 'Model has been saved' );
$this->redirect ( [
'music-entry',
'id' => $model->id
] );
}
}
return $this->render ( 'music-entry', [
'model' => $model
] );
}
I've tried getting the value of artist and title after loading the model using $_POST and it has the values I inputted in the form. Given this, why is the input values saved as null in the database?

After further tweaking, I found the cause of the problem in the model. I had to remove the declaration for $artist and $title. I'm still not sure though why adding those variables caused such problem. Still looking into it.

Related

Laravel model attributes null when i saved it but but I have validated them in the constructor

working with Laravel PHP, I have this model with a constructor where i set the attributes:
class NutritionalPlanRow extends Model
{
use HasFactory;
private $nutritional_plan_id;
private $aliment_id;
private $nomeAlimento;
public function __construct($plan = null,
$aliment = null,
array $attributes = array()) {
parent::__construct($attributes);
if($plan){
$this->nutritional_plan()->associate($plan);
$this->nutritional_plan_id = $plan->id;
}
if($aliment){
$this->aliment()->associate($aliment);
$this->aliment_id = $aliment->id;
$this->nomeAlimento = $aliment->nome;
}
}
/**
* Get the plan that owns the row.
*/
public function nutritional_plan()
{
return $this->belongsTo('App\Models\NutritionalPlan');
}
/**
* Get the aliment record associated with the NutritionalPlanRow.
*/
public function aliment()
{
return $this->belongsTo('App\Models\Aliment');
}
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = [];
/**
* Get the value of nomeAlimento
*/
public function getNomeAlimentoAttribute()
{
return $this->nomeAlimento;
}
/**
* Get the value of plan_id
*/
public function getNutritional_Plan_IdAttribute()
{
return $this->nutritional_plan_id;
}
/**
* Get the value of aliment_id
*/
public function getAliment_IdAttribute()
{
return $this->aliment_id;
}
}
Then I have a controller where I initialize the object:
public function addAlimentToPlan(Request $request){
$planId = $request->planId;
$alimentId = $request->alimentId;
$validatedData = Validator::make($request->all(), [
'planId' => ['required'],
'alimentId' => ['required'],
]);
if ($validatedData->fails()) {
return back()->withErrors($validatedData, 'aliment');
}
$plan = NutritionalPlan::find($planId);
$aliment = Aliment::find($alimentId);
$nutritionalPlanRow = new NutritionalPlanRow($plan, $aliment);
Log::info('Nome Alimento '.$nutritionalPlanRow->getNomeAlimentoAttribute());
$nutritionalPlanRow->save(); //
Toastr::success( 'Alimento aggiunto', '',
["positionClass" => "toast-bottom-right",
"closeButton" => "true"]);
return back();
}
The save operation return this error:
SQLSTATE[23502]: Not null violation: 7 ERRORE: null value in column "nomeAlimento" of relation "nutritional_plan_rows"
but logging the $nutritionalPlanRow->getNomeAlimentoAttribute() the attribure is enhanced.
Someone can help me?
Thank you.
In your constructor you have the following line:
$this->nomeAlimento = $aliment->nome;
You believe that this will fill the attribute in the eloquent model, but that is not happening. Normally such an assignment will pass the magic __set method on the model, but not during model/object construction.
You actually assign it to a property on the object, which is later accessible by your log function, but eloquent doesn't know about it. Therefore it is not sent to the database, resulting in a null error (no default value).
You may use the following to set the values in the constructor:
$this->setAttribute('nomeAlimento', $aliment->nome);
This calls the setAttribute function on the eloquent model, the attribute this becomes part of the model.
(Make sure to change also the other line in your constructor where you assign a value to the object)

I want to acquire the relation value with the store when searching for a category in Laravel5.6

thank you view my question.
I would like to retrieve information on the tag table relation with the store with many-to-many when searching for a category
I created Store-table, Category-table, Tag-table.
The store-table and the category-table are connected by a many-to-many relation. The tag-table is the same.
I was able to search for categories and get information on businesses that are relation- ed, but I do not know how to get information on tags that are relations with stores.
So, I try this idea. search categories → get storeID from relation data→ storeID search → return shop data that hit.
However, I do not know how to get storeID in the store data acquired by category search
How can I write the code?
please help me.
sorry, bat my English.
App\Store
use Illuminate\Database\Eloquent\Model;
class Store extends Model
{
protected $fillable = ['name','location', 'price', 'open_time',
'closed_day'];
protected $table = 'stores';
public function photos(){
return $this->hasMany(StorePhoto::class);
}
public function categories(){
return $this->belongsToMany(Category::class,'category_store','category_id','store_id');
}
public function tags(){
return $this->belongsToMany(Tag::class, 'store_tag', 'tag_id', 'store_id');
}
}
App\Category
protected $fillable = ['store_id', 'category_id'];
public function stores()
{
return $this->belongsToMany(Store::class,'category_store','store_id','category_id');
}
App\Tag
protected $fillable = ['store_id', 'tag_id'];
public function stores()
{
return $this->belongsToMany(Store::class, 'store_tag', 'store_id', 'tag_id');
}
Resource/Category
class Category extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'store' => $this->stores,
];
}
}
web.php
use App\Category;
use App\Http\Resources\Category as CategoryResource;
Route::get("/store/api/category", function (Request $request) {
$search_category = $request->get('category_id');
return new CategoryResource(Category::find($search_category));
});
You can use dot notation to eager load nested relations:
$category = Category::with('stores.tags')->find($request->get('category_id'));
The tags will then be accessible on each Store model related to the Category:
// create a single flattened array of all the tags
$tags = $category->stores->flatMap->tags;

Yii 2: virtual fields in ActiveRecords

I use MySQL and Yii 2. In database exist table 'Regions' with column 'coordinates'. Type of this column is point.
In SQL I can write:
"SELECT X(coordinates) as x, Y(coordinates) as y" and "INSERT INTO Regions SET coordinates = PointFromText('POINT(".$x." ".$y.")')".
But I don't know how make ActiveRecord model. I want this (unchanged the database):
$item = Regions::findOne(1);
echo $item->x." ".$item->y;
$item->x = $new_x;
$item->y = $new_y;
$item->save(); // data saved in 'coordinates' column
Methods 'set...()' and 'get...()' not help me. I want to avoid additional queries to the database.
Please help me to do it.
You can do it with Yii2 just like that:
public $longitude, $latitude;
/**
* #inheritdoc
*/
public function beforeSave($insert)
{
$this->location = new \yii\db\Expression("GeomFromText(:point)", [
':point'=>'POINT('. $this->longitude.' '.$this->latitude.')'
]);
return parent::beforeSave($insert);
}
/**
* #inheritdoc
*/
public static function find()
{
return parent::find()->select([
'*', 'X(location) as longitude', 'Y(location) as latitude'
]);
}

Yii receiving data from checkboxlist

I have some project in Yii. First it was a form with two text fields: Name and Subject (subject is list of subjects separated by comma). Now I need to replace subject text field with list of checkboxes, which will add the same string separated by comma.
<!--<?php echo $form->labelEx($model,'Subjects'); ?>
<?php echo $form->textField($model,'Subjects',array('size'=>60,'maxlength'=>255)); ?>
<?php echo $form->error($model,'Subjects'); ?>-->
<?php echo $form->labelEx($model,'Subjects'); ?>
<?php echo $form->checkBoxList($model,'Subjects',$this->listOfSubjects()); ?>
<?php echo $form->error($model,'Subjects'); ?>
List of subjects is a controller method that returns array required for checkboxlist in Yii, something like:
array(
'1'=>'Something',
'2'=>'Anotherthing'
);
Also here is code of my action create. It's rather standart:
public function actionCreate()
{
$model=new CrdTeachers;
if(isset($_POST['CrdTeachers']))
{
$model->attributes=$_POST['CrdTeachers'];
if($model->save())
$this->redirect(array('view','id'=>$model->Teacher_ID));
}
$this->render('create',array(
'model'=>$model,
));
}
This code worked fine when there was just two text fields. Now when I'm using create action it says that mistake:
mb_strlen() expects parameter 1 to be string, array given
I can't find where can I process it's data to make it string. Any experts of Yii here? What should I look for?
UPDATE:
Here is CRDTeachers model class
class CrdTeachers extends CActiveRecord
{
/**
* Returns the static model of the specified AR class.
* #param string $className active record class name.
* #return CrdTeachers the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'crd_teachers';
}
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('Name, Subjects', 'required'),
array('Name, Subjects', 'length', 'max'=>255),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('Teacher_ID, Name, Subjects', 'safe', 'on'=>'search'),
);
}
/**
* #return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
//'rSubjects'=>array(self::HAS_MANY, 'CrdSubjects', 'Subject_ID'),
//'categories'=>array(self::MANY_MANY, 'CrdTeachers', '{{CrdSubjects}}(Subject_ID, Subject_Name)'),
);
}
public function behaviors()
{
return array(
'DMultiplyListBehavior'=>array(
'class'=>'DMultiplyListBehavior',
'attribute'=>'categoriesArray',
'relation'=>'categories',
'relationPk'=>'id',
),
);
}
protected function afterSave()
{
//$this->refreshCategories();
parent::afterSave();
}
protected function refreshCategories()
{
$categories = $this->categoriesArray;
CrdTeachers::model()->deleteAllByAttributes(array('Subject_ID'=>$this->id));
if (is_array($categories))
{
foreach ($categories as $id)
{
if (Category::model()->exists('id=:id', array(':id'=>$id)))
{
$postCat = new CrdTeachers();
$postCat->post_id = $this->id;
$postCat->category_id = $id;
$postCat->save();
}
}
}
}
/**
* #return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'Teacher_ID' => 'Teacher',
'Name' => 'Name',
'Subjects' => 'Subjects',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
* #return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('Teacher_ID',$this->Teacher_ID);
$criteria->compare('Name',$this->Name,true);
$criteria->compare('Subjects',$this->Subjects,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
/*
* Возвращает список по ID
*/
public function getParentTypeById($id) {
$title = $this->model()->findByPk($id)->Name;
return $title;
}
}
You may use this method in your model.
public function beforeValidate()
{
if (is_array($this->Subjects)) {
$this->Subjects = implode(', ', $this->Subjects);
}
return parent::beforeValidate();
}
You can process the input before validation with the beforeValidate function in the model. Make sure that you run the parent method and return true if want validation to continue. Usually it is done like this:
public function beforeValidate()
{
// do stuff to transform the array into the string
return parent::beforeValidate();
}

FindBySql in yii returns null value

I am new to yii. I am facing a proble with findBySql Method. While i am trying to get a record through passing Mysql query and parameter, it returns me a null value.
Here my code looks like this..
In Model i have defined a function getCountry() to get the country name.
class StateMaster extends CActiveRecord
{
public function tableName()
{
return 'T_State_Master';
}
public function getCountry($c_id)
{
//return array(StateMaster::model()->findBySql("select C_Name from T_Country_Master where C_Id=:CountryId;",array(':CountryId'=>$c_id)));
$result = array(StateMaster::model()->findBysql("select C_Name from T_Country_Master where C_Id={$c_id}"));
return $result;
}
/**
* Returns the static model of the specified AR class.
* Please note that you should have this exact method in all your CActiveRecord descendants!
* #param string $className active record class name.
* #return StateMaster the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
Then in my view file trying to get the country name by providing the Country Id to it.
<?php $this->widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
array(
'label'=>'State Name',
'value'=>$model->S_Name,
),
array(
'label'=>'Country Name',
'value'=>$model->getCountry($model->C_Id),
),
array(
'label'=>'Created Date',
'value'=>Yii::app()->dateFormatter->format("dd-MMM-yyyy", $model->CreatedDt),
),
array(
'label'=>'Created By',
'value'=>$model->CreatedBy,
),
),
)); ?>
whether i wonder why is it not giving me the result.
I have checked the parameter passed into it and its successfully passing.
Please give me solution.
Thanks in advance
change your function to this:
public function getCountry($c_id)
{
$query = "select C_Name from T_Country_Master where C_Id={$c_id}";
//return Yii::app()->db->createCommand($query)->queryAll(); // returns an array, so in your detail view, you must handle it first
return Yii::app()->db->createCommand($query)->queryScalar();
}
Try this way, but if i were you, i will use first one.
public function getCountry($c_id)
{
$query = "select C_Name from T_Country_Master where C_Id={$c_id}";
return Yii::app()->db->createCommand($query)->queryScalar();
}
OR
public function getCountry($c_id)
{
$criteria = new CDbCriteria;
$criteria->select="C_Name";
$criteria->addCondition('C_Id = $c_id');
$result = StateMaster::model()->find($criteria);
return $result;
}

Categories