FindBySql in yii returns null value - php

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;
}

Related

Laravel get Model by Table Name

Is there any way to get a model by table name?
For example, I have a "User" model, its table is defined as protected $table = "users"
Now, what I want to do is to get the model by table name which is equal to "users".
This function is more like the reverse of Model::getTable();
I have searched everywhere but I could not find a solution, perhaps I might be missing something simple?
EDIT
I am building something like an API :
Route::get('/{table}', 'ApiController#api');
Route::get('/{table}/filter', 'ApiController#filter');
Route::get('/{table}/sort', 'ApiController#sort');
Route::get('/{table}/search', 'ApiController#search');
so in the address bar, for example when I search for the "users", I could just hit on the URL:
api/users/search?id=1
then on the controller, something like:
public function search(){
// get all the params
// get the model function
$model = //function to get model by table name
// do some filtering, then return the model
return $model;
}
Maybe something like this will help you:
$className = 'App\\' . studly_case(str_singular($tableName));
if(class_exists($className)) {
$model = new $className;
}
studly_case() and str_singular() are deprecated functions.
You can use the Illuminate\Support\Str facade.
$className = 'App\\' . Str::studly(Str::singular($tableName));
I know that it is an old question, but it can help someone:
public function getModelFromTable($table)
{
foreach( get_declared_classes() as $class ) {
if( is_subclass_of( $class, 'Illuminate\Database\Eloquent\Model' ) ) {
$model = new $class;
if ($model->getTable() === $table)
return $class;
}
}
return false;
}
It will return the class name, so you need to instantiate it.
You must determine for which table name which class to call.
I see 2 ways to do this.
Use Laravel's models naming convention as #IgorRynkovoy suggested
or
Use some kind of dictionary
public function search($tableName)
{
$dictionary = [
'table_name' => 'CLASS_NAME_WITH_NAMESPACE',
'another_table_name' => 'CLASS_NAME_WITH_NAMESPACE',
];
$className = $dictionary[$tableName];
$models = null;
if(class_exists($className)) {
$models = $className::all();
}
// do some filtering, then return the model
return $models;
}
Alternative variant.
I have my base model App\Models\Model
This model have static method getModelByTable, ofcourse you can store this method anywhere you want.
public static function getModelByTable($table)
{
if (!$table) return false;
$model = false;
switch ($table) {
case 'faq':
$model = Faq::class;
break;
case 'faq_items':
$model = FaqItems::class;
break;
}
if ($model) {
try {
$model = app()->make($model);
} catch (\Exception $e) {
}
}
return $model;
}
Inherit from the following, instead of from Model.
use Illuminate\Support\Str;
class EnhancedModel extends \Illuminate\Database\Eloquent\Model
{
/**
* The table associated with the model. Copies $table in Model
*
* #var string
*/
protected static string $tableName;
/**
* Get the table associated with the model. Copies getTable() in Model
*
* #return string
*/
public static function getTableName(): string
{
return static::$tableName ?? Str::snake(Str::pluralStudly(class_basename(static::class)));
}
/**
* Get the table associated with the model. Overrides getTable() in Model
*
* #return string
*/
public function getTable(): string
{
return $this::getTableName();
}
}
To override the auto-guessed table name, add this to your EnhancedModel descendent class:
protected static string $tableName = 'the_table_name';
Looks Laravel 6 make some changes. The following works fine for me
use Illuminate\Support\Str;
....
$className = 'App\\' . Str::studly(str::singular($table_name));
if(class_exists($className)) {
$model = new $className;
}

Yii 2.0 - Input values saved as null in database

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.

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();
}

Yii framework: get sum by scope

I have scopes in my User model:
public function scopes()
{
return array(
'sumPrice'=>array(
'select'=>'SUM(`price`)',
),
);
}
And I want get sumPrice in controller, but I dont know what is a way to do this. I tried:
$sumPrice=User::model()->sumPrice(); //it returns empty record (user model filled by NULLs)
$sumPrice=User::model()->sumPrice()->count(); //it returns count records in user
$sumPrice=User::model()->sumPrice()->findAll(); //it returns all records in user
But there isn't function which return sum, so how to get it?
Solved:
$sumPrice = Yii::app()->db->createCommand('SELECT SUM(`price`) AS `sum` FROM `user`')->queryAll();
var_dump($sumPrice[0]['sum']);
You need a Statistical query on your active record, define a relation on your model
class Post extends CActiveRecord
{
public function relations()
{
return array(
'commentCount'=>array(self::STAT, 'Comment', 'post_id'),
'categoryCount'=>array(
self::STAT, 'Category', 'post_category(post_id, category_id)'
),
);
}
}
Yiiframework
you can use ActiveRecord :
$criteria = new CDbCriteria;
$criteria->select='SUM(your_column) as sum';
$criteria->condition='your_condition';
$user = User::model()->find($criteria);
and you need to declare: public $sum; in your model class. (Using the above example.)

Categories