2

I have the following 3 tables:

Rule
-id
-name

CombinedRule
-id
-name

RuleCombineMapping
-id_rule
-id_combine

I generated a CRUD for Rule and for the CombinedRule table. Inside the CombinedRule model class I created a mapping the class looks like the following:

<?php

namespace app\models;

use Yii;

/**
 * This is the model class for table "combinedrule".
 *
 * @property integer $id
 * @property string $name
 */
class CombinedRule extends \yii\db\ActiveRecord {

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

    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [['name'], 'string', 'max' => 255],
            [['name'], 'unique']
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        return [
            'id' => 'ID',
            'name' => 'Name',
        ];
    }

    public function getRules() {
        return $this->hasMany(Rule::className(), ['id' => 'id_rule'])
                        ->viaTable(RuleCombineMapping::tableName(), ['id_combine' => 'id']);
    }

}

Without success I tried to access the rules of a certain CombinedRule by using the following lines inside the CombinedRuleController.

$t = CombinedRule::find($id);
var_dump($t->rules);

The results is always a 'Unknown Property' exception.

Now I want to view/update/read/delete not only Rules and CombinedRules but also the relation between those two.

I know this is possible in other frameworks using doctrine and I also know how to do it manually first fetching the relation and then adding it to a list.

Now does anybody has a working example how to map this tables using a similar established data structure and also integrate it as easy as possible in the Gii CRUD using its front-end models, views and forms?

lony
  • 6,733
  • 11
  • 60
  • 92
  • `getRules()` looks okay. However, you could try to replace the method body with `return [];` to see if the exception disappears. You could also rename the Rule class and method for finding out if it conflicts with [Model::rules()](http://www.yiiframework.com/doc-2.0/yii-base-model.html#rules%28%29-detail). Example is available in the [docs](http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#relations-via-a-junction-table) or [here](http://stackoverflow.com/a/26781976/57091). – robsch Jun 01 '15 at 19:48
  • I already read the two sites you pointed out, I couldn't find help there sadly. The `[]` brackets are not helping also. Even a name change for the property did not help ....I'm really stuck. I even think about writing my own queries! – lony Jun 02 '15 at 08:01
  • Is `$t` really a CombinedRule object? Is `CombinedRule::find($id)` the gii default generated implementation? What do you see when you var_dump? – robsch Jun 02 '15 at 09:08
  • I get a `ActiveQuery`class with `public 'modelClass' => string 'app\models\CombinedRule' (length=23)` – lony Jun 02 '15 at 09:33
  • This is a hint. Instead of the expected Rule array you get the unexecuted ActiveQuery object. All 3 classes are inherited from ActiveRecord? You could post your model classes as well. And you did not overwrite getAttribute or anything like that? – robsch Jun 02 '15 at 11:51
  • I just used Gii and then added the `hasMany`. I added the model class completely. – lony Jun 02 '15 at 12:56

1 Answers1

0

I've tried it now myself and it worked for me. That is, var_dump($model->rules); in view file gave me an array with Rule objects as expected.

Here are my gii generated files. I have removed comments, attributeLabels(), rules() methods from model classes and action methods and behaviours() from the controller class. So this is the essential code that is required to make $model->rules working:

Rule

class Rule extends \yii\db\ActiveRecord {
    public static function tableName() {
        return 'rule';
    }
}

CombinedRule

class CombinedRule extends \yii\db\ActiveRecord {
    public static function tableName() {
        return 'combined_rule';
    }

    // Added this manually, this does not come from gii!
    // It is the single code that I've added.
    public function getRules() {
        return $this->hasMany(Rule::className(), ['id' => 'id_rule'])
            ->viaTable(RuleCombineMapping::tableName(), ['id_combine' => 'id']);
    }
}

RuleCombineMapping

Gii has also generated two methods getIdCombine() and getIdRule() which are also not essential for the issue.

class RuleCombineMapping extends \yii\db\ActiveRecord {
    public static function tableName() {
        return 'rule_combine_mapping';
    }
}

CombinedRuleController

class CombinedRuleController extends Controller {

    public function actionView($id) {
        return $this->render('view', [
            'model' => $this->findModel($id),
        ]);
    }

    protected function findModel($id) {
        if (($model = CombinedRule::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
}

views/combined-rule/view.php

Just added var_dump($model->rules);. Other is gii generated code.

use yii\helpers\Html;
use yii\widgets\DetailView;

$this->title = $model->title;
$this->params['breadcrumbs'][] = ['label' => 'Combined Rules', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="combined-rule-view">

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

    <p>
        <?= Html::a('Update', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
        <?= Html::a('Delete', ['delete', 'id' => $model->id], [
            'class' => 'btn btn-danger',
            'data' => [
                'confirm' => 'Are you sure you want to delete this item?',
                'method' => 'post',
            ],
        ]) ?>
    </p>

    <?= DetailView::widget([
        'model' => $model,
        'attributes' => ['id', 'title'],
    ]) ?>

    <?php
        // And here it is: an array of Rule objects!!!!! 
        var_dump($model->rules);
    ?>
</div>
robsch
  • 9,358
  • 9
  • 63
  • 104
  • Your code works for me! Thank you! Why did you add the mappings in `RuleCombineMapping`? Do you know how to handle the`Rules` inside the CombinedRuleController even further, e.g. Update/Create? – lony Jun 02 '15 at 20:53
  • @lony Sorry, I don't get what you're asking. Do you mean getIdCombine() and getIdRule()? They were generated by gii. I removed them now since they are not required as it seems. I have removed also some other code that was not essential. Please have a look if this works for you as well. It would be interesting to know in which way your code has differed from the code here. Can you find that out and tell us? And what would you like to know about Update/Create? – robsch Jun 03 '15 at 06:47
  • Yes I meant the `getIdXY`thingy. Which wasn't generated for me. Do you use `yii-basic-app-2.0.4`as well? – lony Jun 03 '15 at 07:25
  • @lony Yes, I did. I might have used other settings in gii. Anyway, the methods weren't important. – robsch Jun 03 '15 at 07:33
  • I debugged this further! The problem seems to be that inside the controller something is missing to access the model property or even the model itself. Inside the view it is fine! `public function actionView($id) {$t = CombinedRule::find($id); var_dump($t->rules); }` – lony Jun 03 '15 at 18:32
  • I created a follow up question [here](http://stackoverflow.com/questions/30628269/yii2-crud-for-mn-data-widgets-and-processing) – lony Jun 03 '15 at 18:50