public function getResource() {
return $this->hasOne(User::className(), ['id' => 'resource_id']);
}
this function working fine but when i use this
public function getResource() {
$model = ucfirst($this->resource_type);
return $this->hasOne($model::className(), ['id' => 'resource_id']);
}
its give me error "Class 'User' not found".
Thanks
you have to use the name including namespace if you specify it dynamically.
public function getResource() {
$model = "api\\models\\".ucfirst($this->resource_type);
return $this->hasOne($model::className(), ['id' => 'resource_id']);
}
Related
How do I handle multiple inverse relations pointing to the same active record?
For example:
class Bicycle extends ActiveRecord {
public function getFrontWheel() {
return $this
->hasOne(Wheel::class, ['id' => 'front_wheel_id'])
->inverseOf('bicycles');
}
public function getRearWheel() {
return $this
->hasOne(Wheel::class, ['id' => 'rear_wheel_id'])
->inverseOf('bicycles');
}
}
class Wheel extends ActiveRecord {
public function getBicycles() {
return $this
->hasMany(Bicycle::class, ['???' => 'id'])
->inverseOf('??????');
}
}
What can I do here? I critically need the inverse relations.
Here is my own solution.
Key points:
It all boils down to proper naming.
Inverse relations are bijective! In other words, every relation always has to have its own unique mirror relation on the other end.
class Bicycle extends ActiveRecord {
public function getFrontWheel() {
return $this
->hasOne(Wheel::class, ['id' => 'front_wheel_id'])
->inverseOf('frontWheelBicycles');
}
public function getRearWheel() {
return $this
->hasOne(Wheel::class, ['id' => 'rear_wheel_id'])
->inverseOf('rearWheelBicycles');
}
}
class Wheel extends ActiveRecord {
public function getFrontWheelBicycles() {
return $this
->hasMany(Bicycle::class, ['front_wheel_id' => 'id'])
->inverseOf('frontWheel');
}
public function getRearWheelBicycles() {
return $this
->hasMany(Bicycle::class, ['rear_wheel_id' => 'id'])
->inverseOf('rearWheel');
}
}
i would suggest to do the following:
create two new classes:
class FrontWheel extends Wheel {
class RearWheel extends Wheel {
in new classes you can set easily the relation.
How to instantiate the correct class? There is a method in ActiveRecord instantiate() where you can write your logic which wheel class need to be created.
class Wheel extends ActiveRecord {
...
public static function instantiate ( $row ) {
if($row['type'] === 'RearWheel') {
return new RealWheel();
}
...
}
full code:
class Bicycle extends ActiveRecord
{
public function getFrontWheel()
{
return $this
->hasOne(Wheel::class, ['id' => 'front_wheel_id'])
->inverseOf('bicycles');
}
public function getRearWheel()
{
return $this
->hasOne(Wheel::class, ['id' => 'rear_wheel_id'])
->inverseOf('bicycles');
}
}
abstract class Wheel extends ActiveRecord
{
public static function instantiate($row)
{
if ($row['type'] === 'RearWheel') {
return new RealWheel();
}
if ($row['type'] === 'FrontWheel') {
return new FrontWheel();
}
throw new InvalidConfigException();
}
abstract public function getBicycles();
}
class RealWheel extends Wheel
{
public function getBicycles()
{
return $this
->hasMany(Bicycle::class, ['rear_wheel_id' => 'id'])
->inverseOf('rearWheel');
}
}
class FrontWheel extends Wheel
{
public function getBicycles()
{
return $this
->hasMany(Bicycle::class, ['front_wheel_id' => 'id'])
->inverseOf('frontWheel');
}
}
I am trying to create simple singleton in yii2 contoller. Maybe i misunderstood something about this pattern but i decide to try. So i have a CRUD. When i got one instance of that class in the db and i decide to update it, the $instance variable is empty(null). Is it because of the page reloading after the creation of the instance and that's why my static variable is set to null again? And is it even possible to make it like this or i am really, really on wrong way? Thank you in advance!
<?php
namespace backend\controllers;
use backend\models\DeliveryTime;
use yii\data\ActiveDataProvider;
use Yii;
class DeliveryTimeController extends \yii\web\Controller
{
public static $instance = null;
public function actionIndex()
{
$delivery = new ActiveDataProvider([
'query' => DeliveryTime::find()->where('id>0')
]);
return $this->render('index', ['delivery' => $delivery]);
}
public static function setInstance()
{
if(self::$instance == null){
self::$instance = new DeliveryTime();
}
return self::$instance;
}
public static function getInstance(){
return self::$instance;
}
public function actionCreate()
{
$delivery = DeliveryTimeController::setInstance();
if($delivery->load(Yii::$app->request->post()) && $delivery->save()){
self::$instance = $delivery;
return $this->redirect(['index']);
}
return $this->render('create', ['model' => $delivery]);
}
public function actionUpdate()
{
$delivery = DeliveryTimeController::getInstance();
if($delivery->load(Yii::$app->request->post()) && $delivery->save()){
return $this->render(['index']);
}
return $this->render('update', ['model' => $delivery]);
}
public function actionDelete(){
$delivery = DeliveryTimeController::getInstance();
if($delivery != null){
$delivery->delete();
return $this->redirect(['index']);
}
}
}
For design patterns i would recommend to check out
https://github.com/kamranahmedse/design-patterns-for-humans
https://github.com/edin/php-design-patterns (my github repo :)
For what you are trying it's better to just create new instance.
I want to implement user login into yii2 basic app.everything works properly except, when I tries to access Yii::$app->user->isGuest on layout main page. it always returns true. whats going wrong here?, please help me
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
Yii::$app->user->isGuest; // i m getting this as false, which is correct, but after goBack(), I m getting it as true
return $this->goBack();
}
return $this->render('login', [
'model' => $model,
]);
}
Login Mehod from LoginForm.php
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
}
return false;
}
Note : I am using custom theme, which rests outside the web folder and inside project/themes/ directory
** User Model is as follows**
<?php
namespace app\models;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
use yii\web\NotFoundHttpException;
class User extends ActiveRecord implements IdentityInterface {
private $id;
private $authKey;
const STATUS_DELETED = '0';
const STATUS_ACTIVE = '10';
public static function tableName() {
return '{{%user}}';
}
/**
* #inheritdoc
*/
public function behaviors() {
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function getId() {
return $this->id;
}
/**
* #inheritdoc
*/
public function getAuthKey() {
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey) {
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password) {
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
public static function findByEmail($email) {
$user_type = ['U'];
return static::find()
->andWhere('email = :email', [':email' => $email])
->andFilterWhere(['in', 'user_type', $user_type])
->one();
}
public static function findIdentity($id) {
$user = static::find()->where(['id' => $id, 'status' => self::STATUS_ACTIVE,])->one();
if (empty($user->id)) {
\Yii::$app->session->destroy();
}
return $user;
}
public static function findIdentityByAccessToken($token, $type = null) {
$user = static::find()
->where([
'access_token' => $token,
'status' => self::STATUS_ACTIVE,
])
->one();
if (!empty($user)) {
return $user;
} else {
throw new NotFoundHttpException('Invalid access token.');
}
}
}
Remove the lines:
private $id;
private $authKey;
from User class.
You should not directly declare ActiveRecord attributes that come from database as stated in the Guide.
Note: The Active Record attributes are named after the associated table columns in a case-sensitive manner. Yii automatically defines an attribute in Active Record for every column of the associated table. You should NOT redeclare any of the attributes.
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.
I have an AccessFilter Class
class ProjectAccessControl extends \yii\base\ActionFilter
{
public $a;
/**
* #inheritdoc
*/
public function beforeAction($action)
{
switch ($action->id) {
case 'view':
// code here
break;
}
}
In controller I revoke this AccessFilter in behaviour() method like this:
public function behaviors()
{
return [
'access' => [
'class' => ProjectAccessControl::className(),
]
];
}
Now I want to pass the $a variable from AccessFilter to an any action in Controller. How to do that?
You should simply add a variable in your controller, e.g. :
public $a;
And use this in your filter :
$this->owner->a = $this->a;