Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix ‘"frontend\models\model" must have a primary key’ error in Yii2 advanced template

Tags:

php

yii2

I'm trying to create a model, apparently all process is right but when I try to show his error in a view (immediately after creating the model) Yii2-app throws

Invalid Configuration – yii\base\InvalidConfigException - "frontend\models\mystore\Staff" must have a primary key.

The only way to solve this problem (until now) is restart MySQL service from my local server and refresh the page on browser, after this my application shows all data without errors, until I create a new record.

I'm using XAMPP like my local server and MySQL like database management system and when I use phpmyadmin to search the new records, all is right, the PK was created and all data is stored correctly.

Model


namespace frontend\models\mystore;

use Yii;
use frontend\models\basic\PersonalData;
use frontend\models\mystore\Charges;
use frontend\models\mystore\MyStore;
use common\models\User;


/**
 * This is the model class for table "staff".
 *
 * @property int $id
 * @property int $store_id
 * @property string $code 
 * @property int $personal_data_id
 * @property int $charge_id 
 * @property int $active
 * @property int $created_at
 * @property int $updated_at
 * @property int $visible
 * @property int $user_id
 *
 * @property SaleOrders $saleOrders
 * @property User $user
 * @property Charges $charge
 * @property MyStore $store
 * @property PersonalData $personalData
 */
class Staff extends \yii\db\ActiveRecord
{
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'staff';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['store_id', 'personal_data_id', 'charge_id', 'active', 'created_at', 'updated_at', 'visible', 'user_id'], 'integer'],
            [['code'], 'string', 'max' => 15],
            [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
            [['charge_id'], 'exist', 'skipOnError' => true, 'targetClass' => Charges::className(), 'targetAttribute' => ['charge_id' => 'id']],
            [['store_id'], 'exist', 'skipOnError' => true, 'targetClass' => MyStore::className(), 'targetAttribute' => ['store_id' => 'id']],
            [['personal_data_id'], 'exist', 'skipOnError' => true, 'targetClass' => PersonalData::className(), 'targetAttribute' => ['personal_data_id' => 'id']],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'store_id' => 'Store ID',
            'code' => 'Code',
            'personal_data_id' => 'Personal Data ID',
            'charge_id' => 'Charge ID',
            'active' => 'Active',
            'created_at' => 'Created At',
            'updated_at' => 'Updated At',
            'visible' => 'Visible',
            'user_id' => 'User ID',
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getSaleOrders()
    {
        return $this->hasOne(SaleOrders::className(), ['salesman_id' => 'id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getUser()
    {
        return $this->hasOne(User::className(), ['id' => 'user_id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getCharge()
    {
        return $this->hasOne(Charges::className(), ['id' => 'charge_id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getStore()
    {
        return $this->hasOne(MyStore::className(), ['id' => 'store_id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getPersonalData()
    {
        return $this->hasOne(PersonalData::className(), ['id' => 'personal_data_id']);
    }
}

Controller

/**
 * Creates a new Staff model.
 * If creation is successful, the browser will be redirected to the 'index' page.
 * @return mixed
 */
public function actionCreate()
{
    $transaction = \Yii::$app->db->beginTransaction();

    try{
        $staffModel = new Staff();
        $isValid = false;

        $personalDataModels = $this->processPersonalData();// create, load and save personal information, return array with models
        $signupModel = $this->signup(); // create new account
        $personal_data_id = $personalDataModels['persDataModel']->getPrimaryKey(); // get PK when model is stored, get model if not

        if( $personal_data_id && is_int($signupModel) ){ // personal data && user saved correctly

            $staffModel->load(Yii::$app->request->post()); // the only field to be loaded is "code" who is not required

            $staffModel->setAttributes(['store_id' => Yii::$app->user->identity->store, 'personal_data_id' => $personal_data_id, 'active' => 1, 'user_id' => $signupModel ]); // populate the staff model

            $isValid = $staffModel->save();

            if(!$isValid){ // model is not valid
                $transaction->rollBack();
            }
        }

        if($isValid){
            $transaction->commit();

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

        $chargesList = Charges::find()->select(['id', 'name'])->asArray()->all();

        return $this->render('create', [
            'staffModel' => $staffModel,
            'chargesList' => $chargesList,
            'signupModel' => $signupModel,
            'personalModels' => $personalDataModels,
        ]);

    } catch(\Exception $e) {
        $transaction->rollBack();
        throw $e;
    } catch(Exception $e) {
        $transaction->rollback();
    }
}

View


use yii\helpers\Html;
use yii\grid\GridView;

/* @var $this yii\web\View */
/* @var $searchModel frontend\models\mystore\StaffSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = 'Staff';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="staff-index">

    <h1><?= Html::encode($this->title) ?></h1>

    <p>
        <?= Html::a('Create Staff', ['create'], ['class' => 'btn btn-success']) ?>
    </p>

    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
            'code',
            [
                'attribute' => 'name', // public property on searchModel
                'label' => 'Nombre',
                'value' => 'personalData.first_name'// method relation name on main Model . field name
            ],
            [
                'attribute' => 'last_name',
                'label' => 'Apellido',
                'value' => 'personalData.first_last_name'
            ],
            [
                'attribute' => 'charge',
                'label' => 'Cargo',
                'value' => 'charge.name'
            ],
            [
                'attribute' => 'username',
                'label' => 'Nombre de Usuario',
                'value' => 'user.username'
            ],
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
</div>

After create the Staff model I expect browser redirect to the index page and all information can be shown in a gridview, but I get the error mentioned above.

next is the complete error message:

"Invalid Configuration – yii\base\InvalidConfigException
Primary key of 'frontend\models\mystore\Staff' can not be empty."

in C:\xampp\htdocs\myapp\vendor\yiisoft\yii2\db\ActiveQuery.php
  }
                $key = serialize($key);
                if (isset($hash[$key])) {
                    unset($models[$i]);
                } else {
                    $hash[$key] = true;
                }
            }
        } elseif (empty($pks)) {
            throw new InvalidConfigException("Primary key of '{$class}' can not be empty.");
        } else {
            // single column primary key
            $pk = reset($pks);
            foreach ($models as $i => $model) {
                if (!isset($model[$pk])) {
                    // do not continue if the primary key is not part of the result set
                    break;
                }
                $key = $model[$pk];
like image 474
German_Kast Avatar asked Apr 30 '19 22:04

German_Kast


1 Answers

seems that you have not a primary key in your model ( and could be in your table )

you can add a primary key field manually to the model this way
as public static method

  class Staff extends \yii\db\ActiveRecord
  {

      /**
       * {@inheritdoc}
       */
      public static function tableName()
      {
          return 'staff';
      }

     /**
       * @inheritdoc$primaryKey
       */
      public static function primaryKey()
      {
          return ["your_id_column"];
      }

   ........
like image 90
ScaisEdge Avatar answered Nov 08 '22 10:11

ScaisEdge