@hanran_koizoku

Setting read-only property и Trying to get property of non-object Yii2-в чем ошибка?

Возникают две эти ошибки при попытке обновить запись и при попытке добавить новую соответственно.
Возникло из-за замены id из другой таблицы на соответствующее название (пример: таблица фильм туда передается id_жанра, но отображается название жанра)
Код модели:
<?php

namespace common\models;

use Yii;

/**
 * This is the model class for table "cinema".
 *
 * @property integer $id_cinema
 * @property string $Name
 * @property integer $dlitelnost
 * @property integer $Categori
 * @property integer $Price
 * @property integer $Prokatchiki
 *
 * @property Janr $categori
 * @property Dlitelnost $dlitelnost0
 * @property Prokatchiki $prokatchiki
 * @property Tickets[] $tickets
 */
class Cinema extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'cinema';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['id_cinema', 'Name', 'dlitelnost', 'Categori', 'Price', 'Prokatchiki'], 'required'],
            [['id_cinema', 'dlitelnost', 'Categori', 'Price', 'Prokatchiki'], 'integer'],
            [['Name'], 'string', 'max' => 3000],
			[['CategoriName'], 'string','max'=>3000],
			[['TimeName'], 'safe'],
			[['CategoriName'], 'exist', 'skipOnError' => true, 'targetClass' => Janr::className(), 'targetAttribute' => ['CategoriName' => 'Name_janra']],
			[['TimeName'], 'exist', 'skipOnError' => true, 'targetClass' => Dlitelnost::className(), 'targetAttribute' => ['TimeName' => 'Date_premiere']],
            [['Categori'], 'exist', 'skipOnError' => true, 'targetClass' => Janr::className(), 'targetAttribute' => ['Categori' => 'Id_janra']],
            [['dlitelnost'], 'exist', 'skipOnError' => true, 'targetClass' => Dlitelnost::className(), 'targetAttribute' => ['dlitelnost' => 'id_time']],
            [['Prokatchiki'], 'exist', 'skipOnError' => true, 'targetClass' => Prokatchiki::className(), 'targetAttribute' => ['Prokatchiki' => 'Id_Prokatchika']],

			[['CategoriName'], 'exist', 'skipOnError' => true, 'targetClass' => Janr::className(), 'targetAttribute' => ['CategoriName' => 'Name_janra']],
			
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id_cinema' => 'Id Cinema',
            'Name' => 'Name',
            'dlitelnost' => 'Dlitelnost',
            'Categori' => 'Categori',
            'Price' => 'Price',
            'Prokatchiki' => 'Prokatchiki',
			'TimeName'=>'Date Premiere',
			
			 'CategoriName' => 'Janr',
        ];
    }

	public static function getGroupData()
    {
        $data = static::find()->select('id_cinema')->all();

        $value=(count($data)==0)? [''=>'']: \yii\helpers\ArrayHelper::map($data, 'cinema','Id Cinema'); //id = your ID model, name = your captio

        return $value;
    }
    /**
     * @return \yii\db\ActiveQuery
     */
    public function getCategori()
    {
        return $this->hasOne(janr::className(), ['Id_janra' => 'Categori']);
    }
	public function getCategoriName()
    {
        return $this->getCategori()->one()->Name_janra;
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getDlitelnost0()
    {
        return $this->hasOne(Dlitelnost::className(), ['id_time' => 'dlitelnost']);
    }
	public function getTimeName()
    {
        return $this->getDlitelnost()->one()->Date_premiere;
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProkatchiki()
    {
        return $this->hasOne(Prokatchiki::className(), ['Id_Prokatchika' => 'Prokatchiki']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getTickets()
    {
        return $this->hasMany(Tickets::className(), ['id_cinema' => 'id_cinema']);
    }
}


код контроллера:
<?php

namespace backend\controllers;

use Yii;
use common\models\Cinema;
use backend\models\CinemaSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;

/**
 * CinemaController implements the CRUD actions for Cinema model.
 */
class CinemaController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['POST'],
                ],
            ],
        ];
    }

    /**
     * Lists all Cinema models.
     * @return mixed
     */
    public function actionIndex()
    {
        $searchModel = new CinemaSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

    /**
     * Displays a single Cinema model.
     * @param integer $id
     * @return mixed
     */
    public function actionView($id)
    {
        return $this->render('view', [
            'model' => $this->findModel($id),
        ]);
    }

    /**
     * Creates a new Cinema model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate()
    {
        $model = new Cinema();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id_cinema]);
        } else {
            return $this->render('create', [
                'model' => $model,
            ]);
        }
    }


    /**
     * Updates an existing Cinema model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id
     * @return mixed
     */
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id_cinema]);
        } else {
            return $this->render('update', [
                'model' => $model,
            ]);
        }
    }

    /**
     * Deletes an existing Cinema model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param integer $id
     * @return mixed
     */
    public function actionDelete($id)
    {
        $this->findModel($id)->delete();

        return $this->redirect(['index']);
    }

    /**
     * Finds the Cinema model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param integer $id
     * @return Cinema the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id)
    {
        if (($model = Cinema::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
}

код серча:
<?php

namespace backend\models;

use common\models\janr;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use common\models\Cinema;

/**
 * CinemaSearch represents the model behind the search form about `common\models\Cinema`.
 */
class CinemaSearch extends Cinema
{
    /**
     * @inheritdoc
     */
	 public $CategoriName;
    public function rules()
    {
        return [
            [['id_cinema', 'dlitelnost','Categori', 'Price', 'Prokatchiki'], 'integer'],
            [['Name'], 'safe'],
			[['CategoriName'],'string'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = Cinema::find();

        // add conditions that should always apply here

		$myQuery = janr::find()->select(['Id_janra','Name_janra'])->groupBy('Id_janra');
        $query->leftJoin(['CategoriName' => $myQuery], 'CategoriName.Id_janra = Categori');

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);
		
		 $dataProvider->setSort([
            'attributes' => [
                'id_cinema',
                'Name',
                'Categori',
                'CategoriName' => [
                    'asc' => ['CategoriName.Name_janra' => SORT_ASC],
                    'desc' => ['CategoriName.Name_janra' => SORT_DESC],
                    'label' => 'CATEGORI',
                    'default' => SORT_ASC,
                ],
            ]
        ]);

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
		$query->andFilterWhere([
            'id_cinema' => $this->id_cinema,
            'Categori' => $this->Categori,
        ])->andFilterWhere(['like', 'CategoriName.Name_janra', $this->CategoriName]);
        $query->andFilterWhere([
            'dlitelnost' => $this->dlitelnost,
            'Price' => $this->Price,
            'Prokatchiki' => $this->Prokatchiki,
        ]);

        $query->andFilterWhere(['like', 'Name', $this->Name]);

        return $dataProvider;
    }
}
  • Вопрос задан
  • 2114 просмотров
Пригласить эксперта
Ответы на вопрос 2
mitaichik
@mitaichik
Как минимум одна недоработка есть в последнем файле - в переопределении сценриос вызывается метод далекого предка, возможно это дает сбой. В первом файле несколько геттеров без сеттеров - вот вам и реад-онли проперти. В каком файле ошибка? Выложите стектрейс.

И, черт возьми, что это за нейминг? Где руский, где английский, где с большой буквы, где с маленькой, где кемлкейс, где андерскор. Ну как так можно!
Ответ написан
sokollondon
@sokollondon
В большинстве случаев делать set у relation не требуется. Но если Вам это всё-таки нужно:
php composer.phar require la-haute-societe/yii2-save-relations-behavior "*"


Model
class Post extends yii\db\ActiveRecord
{
    public function behaviors()
    {
        return [
            'saveRelations' => [
                'class' => SaveRelationsBehavior::class,
                'relations' => [
                    'author',
                ],
            ],
        ];
    }
}


Теперь такой код не будет вызывать ошибки Setting read-only property =)
$post->author = Author::findOne(2);

Ещё модуль yii2-save-relations-behavior поможет проще сохранять hasMany relations
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы