Yii2 How to create models dynamically and specify relationship among them? - yii2

I am creating tables on the fly. If I created the tables Schools and Classes. How can I create the models for them and specify relationships among them.
I searched but did not get anything on this topic. Any help would be appreciated. Thank you.

The only way I can figure out is to use "global variables" for tables - e.g. in Yii::$app->params['ar_tables'] and redefine them dynamically:
In config:
[
....
'params' => [
'ar_tables' => [
'Parent' => 'parent',
'Child' => 'table2'
]
]
....
]
Parent class:
class Parent extends \yii\db\ActiveRecord
{
public static function tableName()
{
return Yii::$app->params['ar_tables']['Parent'];
}
public function getChildren
{
return self::hasMany(Child::className(), ['parent_id' => 'id']);
}
}
Child class:
class Child extends \yii\db\ActiveRecord
{
public static function tableName()
{
return Yii::$app->params['ar_tables']['Child'];
}
public function getParent
{
return self::hasOne(Parent::className(), ['id' => 'parent_id']);
}
}
After that you can dynamically change Yii::$app->params['ar_tables'] values for getting what you want. I have already tried this. And didn't like :)

Related

Laravel eloquent query with multiple child relations

I am working on a query but can't find the solution to this one.
The structure i have at the moment is:
A project has 1 machine, but a machine can belong to multiple projects.
A machine can have multiple issues.
Now i want to get all projects with the issues created after the project got created.
The query that i have at the moment, but doesn't work:
$allProjects = Project::with(['machine',
'machine.issues' => function ($query) {
$query->where('created_at', '>=', 'project.created_at');
}
])
->orderBy('id')
->get();
I am not getting the issues at all by using this query, when i switch the operator to: < then i get all the issues even the ones after project.created_at
You can have a pivot do most of the work for you. I tried reproducing your problem statement as below.
<?php
class Project extends Model
{
use HasFactory;
public function machine()
{
return $this->hasOneThrough(Machine::class, MachineProject::class, 'machine_id', 'id', 'id', 'project_id');
}
public function issues()
{
return $this->hasManyThrough(Issue::class, Machine::class, 'id', 'machine_id')->whereDate('issues.created_at', '<=', $this->created_at);
}
}
class Machine extends Model
{
use HasFactory;
public $with = ['issues'];
public function projects()
{
return $this->belongsToMany(Project::class);
}
public function issues()
{
return $this->hasMany(Issue::class);
}
}
class Issue extends Model
{
use HasFactory;
public function machine()
{
return $this->belongsTo(Machine::class);
}
}
class MachineProject extends Pivot
{
//
}
To retrieve the Project with issues, you just do
$allProjects = Project::with(['machine' => function ($machine) {
$machine->with('issues');
}])->get();

Make every functions in all controller execute code some code before execute the functions without add the code in every functions in Yii2

I have a code for checking a session isset or not in Yii2, I added the code inside a function in a controller, this is the code
if(!isset($session['selectedMonth'])){
return $this->redirect(['select-period/month']);
return false;
}
I have over than 50 functions in 10 controllers, I want every function use that code, how do I can make it without put that code in every function one by one?
You could create base controller for your app, and extend all other controllers from it. Then you could add beforeAction() method in this base controller, so it will be used by all controllers that inherit from base controller:
public function beforeAction($action) {
// initialize $session here
if(!isset($session['selectedMonth'])){
Yii::$app->response->redirect(['select-period/month']);
return false;
}
return parent::beforeAction($action);
}
You can create simple behavior that will handle 'before action' event, for example:
use Yii;
use yii\base\Behavior;
use yii\base\Controller;
class RedirectBehavior extends Behavior
{
public function events()
{
return [
Controller::EVENT_BEFORE_ACTION => 'beforeAction',
];
}
public function beforeAction($event)
{
if (Yii::$app->session->has('selectedMonth')){
return;
}
Yii::$app->getResponse()->redirect(['select-period/month'])->send();
}
}
and attach it to your controllers
public function behaviors()
{
return [
'redirect' => [
'class' => RedirectBehavior::className(),
],
];
}

custom validation in yii2 model

I am trying to add custom rule to form. I have added a custom function in model but it's not working for me.
class BackendUser extends ActiveRecord implements IdentityInterface
{
public function rules()
{
return [
['username','validateUsername','params'=>'username'=>'username']],
];
}
public function validateUsername($attribute, $params)
{
if (preg_match('/[^a-z])/i', $this->$attribute)) {
$this->addError($attribute, 'Username should only contain
alphabets');
}
}}
In PHP there is no construct like you used here (a => b => c, maybe it's a typo) and you don't have to pass any parameters anyway since you don't use them in the validator method. Simple
public function rules()
{
return [
['username','validateUsername'],
];
}
is enough.
There are few typos in your code. Try using $this->{$attribute} in dynamic attributes and also params key should be an array while calling inline validation.
class BackendUser extends ActiveRecord implements IdentityInterface
{
public function rules()
{
return [
['username','validateUsername','params'=>['username'=>'username']],
];
}
public function validateUsername($attribute, $params)
{
if (preg_match('/[^a-z])/i', $this->{$attribute})) {
$this->addError($attribute, 'Username should only contain alphabets');
}
}
}

Create behavior in yii2

I am using Advanced Template in Yii 2. I want to create behavior for user id, so I made folder in common\components\behavior and created one class,
class UidBehavior extends Behavior
{
public function encryptUid($id)
{
$id = md5($id);
return $this->$id;
}
}
then in user.php =>
'mybehavior' => [
'class' => 'common\components\behavior\UidBehavior',
'encryptUid' => 'id'
],
but error has occurred which is
Setting unknown property: common\components\behavior\UidBehavior::encryptUid
can any one help me ?
You try to init encryptUid property on User.php, Where that is not exist, You can rewrite code like this then all thing work fine:
class UidBehavior extends Behavior
{
public $encryptUid;
public function encryptUid($id)
{
$encryptUid = md5($encryptUid);
return $this->$encryptUid;
}
}
Check Refer Link

Yii2 Active record working: How i can query through relation in yii2 model

Here is my Restaurents model:
class Restaurents extends \yii\db\ActiveRecord
{
public function rules(){
return [
[['name'], 'string'],
];
}
public function getRestaurentInfo(){
return $this->hasOne(RestaurentInfo::className(), ['restaurent_id' => 'id']);
}
}
and my RestaurentInfo model:
class RestaurentInfo extends \yii\db\ActiveRecord
{
public function rules(){
return [
[['address',], 'string']
];
}
public function getRestaurent()
{
return $this->hasOne(Restaurens::className(), ['id' => 'restaurent_id']);
}
}
I want to query a list of restaurents with conditions:
the restaurent have name like $key or the restaurent have address like $key.
How I can do it?
You can do it like this:
$restaurents = Restaurent::find()
->joinWith('restaurentInfo')
->where(['like', 'name', $key])
->orWhere(['like', 'address', $key])
->all();
I'd recommend to spend some time and understand how to work with Active Record and Active Query.