Как вывести в гриде поле из другой таблицы

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Как вывести в гриде поле из другой таблицы

Сообщение svil »

Таблица companies связана с таблицей requisites как один ко многим.
Не могу найти ошибку почему не выводится в гриде поле из таблицы requisites если у записи отмечен флаг NULL (поле default)
Но выводятся все номера
Модель companies

Код: Выделить всё

<?php

namespace app\models;

use Yii;


class Companies extends BaseActiveRecord
{

    public $requisitesNameTelfax;

    public static function tableName()
    {
        return 'companies';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['name'
                //,
               // 'basket'
            ],
                'required'],
            [['name'], 'string'],
          
        ];
    }


    
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'name' => 'Краткое наименование организации',
          

            'requisitesNameTelfax'  => 'Телефон/факс',
          

        ];
    }

  
    /* Геттер для полного наименования компании */
    public function getRequisitesName() {
        return $this->Requisites->fullname;
    }

   

    public function getRequisites()
    {
        return $this->hasMany(Requisites::className(), ['company_id' => 'id']);
    }


  


}



модель Requisites

Код: Выделить всё

<?php

namespace app\models;

use Yii;


class Requisites extends BaseActiveRecord
{
    protected $primaryKey = 'id';
    public $companiesName;
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'requisites';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['fullname'], 'required'],
           ];
    }

    /**
     * {@inheritdoc}
     */


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


    /* Геттер для наименования компании */
    public function getCompaniesName() {
        return $this->Companies->name;
    }


}

Контроллер

Код: Выделить всё

public function actionIndex()
    {
        $searchModel = new CompaniesSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        
        $data__ = Requisites::find()->where(['default'=>null])->all();
      
        foreach ($data__ as $value) {
            $data_telfax[$value->id]=$value->telfax;
        }
        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
           
            'data_telfax' => $data_telfax
        ]);
    }
Вид

Код: Выделить всё

  <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],

            'id',
            'name:ntext',
          
            [
                'attribute' => 'requisitesNameTelfax',
              
                'value' => function($data_telfax){
        foreach ($data_telfax as $key => $value){
           return "\$data_telfax[$key] => $value.\n"; //здесь выводит почему-то id от Провайдера
        }

                },
            ],
            
            ...
            <?php
debug($data_telfax); //здесь нормально выводит поля requisites->telfax . (номера телефонов)
?>
Пыталась и так вывести-ошибка

Код: Выделить всё

Getting unknown property: app\models\Companies::telfax

Код: Выделить всё

 [
                'attribute' => 'requisitesNameTelfax',
              'value' => function($data_telfax){
                    return $data_telfax->telfax;
                

                },
            ],
Меняю связь один к одному - работает
но мне надо один ко многим и флаг использования 1 записи

Код: Выделить всё

 public function getRequisites()
    {
        return $this->hasOne(Requisites::className(), ['company_id' => 'id']);
    }
masson
Сообщения: 545
Зарегистрирован: 2012.07.03, 15:59

Re: Как вывести в гриде поле из другой таблицы

Сообщение masson »

Код: Выделить всё

'value' => function($data_telfax){
        foreach ($data_telfax as $key => $value){
           return "\$data_telfax[$key] => $value.\n"; //здесь выводит почему-то id от Провайдера
        }
Здесь в функцию 1-ым параметром передается модель из DataProvider.
https://www.yiiframework.com/doc/api/2. ... lue-detail

А вам надо так:

Код: Выделить всё

'value' => function($model) use ($data_telfax) {
        foreach ($data_telfax as $key => $value){
           return "\$data_telfax[$key] => $value.\n"; 
        }

Честно говоря я не совсем понял почему в классе модели Requisites св-во id protected, свойств tel_fax & default вообще нет ...
И что вы хотите увидеть в гриде вместо "\$data_telfax[$key] => $value.\n";? Во всех строчках таблицы у вас будет выводиться одно и то же
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: Как вывести в гриде поле из другой таблицы

Сообщение svil »

Как объяснить...
Есть две таблицы, в гриде одной companies стоит вместе с кнопками delete update view Реквизиты(requisites).
И из это самой таблицы requisites при наличии флага 0 выводится номер телефона в поле грида telfax
То есть telfax - поле таблицы requisites, связанной по company_id с таблицей companies
И этих реквизитов может быть много, но действующий тот, у которой флаг 0, этот реквизит по флагу и берем, а значит и выводим номер телефона в грид companies
Может я забыла свойства вывести в companies модель...
masson
Сообщения: 545
Зарегистрирован: 2012.07.03, 15:59

Re: Как вывести в гриде поле из другой таблицы

Сообщение masson »

Тогда в контроллере никаких data не надо, а выбирать так :

Код: Выделить всё

public function actionIndex()
    {
        $searchModel = new CompaniesSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        $dataProvider->query->with([
            'requisites' => function($query) {
                $query->select('telfax')->andWhere(['default' => null]);
            }
        ]);

        ....
А во вьюхе :

Код: Выделить всё

'value' => function($model) {
       $arr = [];
        foreach ($model->requisites as $req) {
           $arr[] = $req->telfax;
        }

        return implode(' ', $arr);
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: Как вывести в гриде поле из другой таблицы

Сообщение svil »

Не получилось. Пустая колонка.

Код: Выделить всё

Getting unknown property: yii\data\ActiveDataProvider::requisites
Контроллер

Код: Выделить всё

 $searchModel = new CompaniesSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        $dataProvider->query->with([
            'requisites' => function($query) {
                $query->select('telfax')->andWhere(['default' => null]);
            }
        ]);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,

        ]);
    }
Вид

Код: Выделить всё

 [
                'attribute' => 'requisitesName',
                'value' => function($dataProvider){
                    $arr = [];
                    foreach ($dataProvider->requisites as $req) {
                        $arr[] = $req->telfax;
                    }

                    return implode(' ', $arr);
                },
            ],
masson
Сообщения: 545
Зарегистрирован: 2012.07.03, 15:59

Re: Как вывести в гриде поле из другой таблицы

Сообщение masson »

Getting unknown property: yii\data\ActiveDataProvider::requisites
На какой строчке?
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: Как вывести в гриде поле из другой таблицы

Сообщение svil »

Функция у меня для просмотра

Код: Выделить всё

function debug($arr){
    echo '<pre>'.print_r($arr, true).'</pre>';
}
В виде набираю

Код: Выделить всё

debug($dataProvider->requisites)
И после этого ошибка

Код: Выделить всё

Getting unknown property: yii\data\ActiveDataProvider::requisites
masson
Сообщения: 545
Зарегистрирован: 2012.07.03, 15:59

Re: Как вывести в гриде поле из другой таблицы

Сообщение masson »

Понятно. Потому что у $dataProvider (который приходит из контроллера) нет такого свойства как requisites. Он есть только у модели. Непонятно зачем вы все это делаете (где вы в виде набираете свой debug, в какой строчке и зачем), я же написал как надо.
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: Как вывести в гриде поле из другой таблицы

Сообщение svil »

При попытке просмотреть $model через echo '<pre>'.print_r($arr, true).'</pre>' . выдает ошибку

Код: Выделить всё

Undefined variable: model
Последний раз редактировалось svil 2019.06.23, 10:36, всего редактировалось 2 раза.
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: Как вывести в гриде поле из другой таблицы

Сообщение svil »

Спасибо за помощь. Я туплю. Но не понимаю вот что.
В контроллере нет $model

Код: Выделить всё


 public function actionIndex()
    {
//        $searchModel = new CompaniesSearch();
//        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
//        $dataProvider->query->andWhere(['basket'=> '0']);

        $searchModel = new CompaniesSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        $dataProvider->query->with([
            'requisites' => function($query) {
                $query->select('telfax')->andWhere(['default' => null]);
            }

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

        ]);
    }
Поэтому и в виде у меня пустая колонка, не понимаю, откуда берется $model в виде

Код: Выделить всё

<?php

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

/* @var $this yii\web\View */
/* @var $searchModel app\models\CompaniesSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = 'Организации';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="companies-index">

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

    <p>
        <?= Html::a('Добавить Организацию', ['create'], ['class' => 'btn btn-success']) ?>
    </p>



    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],

            'id',
            'name:ntext',
            [
                'attribute' => 'requisitesName',
                'value' => function($model) {
                    $arr = [];
                    foreach ($model->requisites as $req) {
                        $arr[] = $req->telfax;
                    }

                    return implode(' ', $arr);
                }
            ],
            ['class' => 'yii\grid\ActionColumn'],
            [
                'class' => 'yii\grid\ActionColumn',
                'template' => '{confirm}',
                'visibleButtons' => [
                    'confirm' => true,
                ],
                'buttons' => [
                    'confirm' => function ($data, $dataProvider) {

                        return Html::a('Реквизиты', ['/requisites/index', 'company_id'=>$dataProvider->id], ['class' => 'btn btn-primary']);
                    },
                ],

            ],
        ],
    ]); ?>


</div>
Может в модели Companies что-то

Код: Выделить всё

<?php

namespace app\models;

use Yii;


class Companies extends \yii\db\ActiveRecord
{
    /**
     * {@inheritdoc}
     */
    public $requisitesName;

    public static function tableName()
    {
        return 'companies';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['name'], 'required'],
            ['name', 'unique'],
            [['name'], 'string'],
            [['basket'], 'integer'],
        ];
    }


    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'name' => 'Краткое наименование организации',
            'basket' => 'Удаление (отметить, если удалить)',
            'requisitesName' => 'Телефон',
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */


    public function getJobs()
    {
        return $this->hasMany(Jobs::className(), ['company_id' => 'id']);
    }

    public function getRequisites()
    {
        return $this->hasMany(Requisites::className(), ['company_id' => 'id']);
    }


    public function getUsers() {

        return $this->hasMany(Users::className(), ['id' => 'user_id'])
            ->viaTable(
                'Jobs',
                ['company_id' => 'companies.id'],
                function ($query) {
                    $query->andWhere(['users.id' => 'jobs.id']);
                });
    }
    /* Геттер для полного наименования компании */
    public function getRequisitesName() {
        return $this->Requisites->telfax;
    }


}

Модель Requisites

Код: Выделить всё

<?php

namespace app\models;

use Yii;


class Requisites extends \yii\db\ActiveRecord
{
    protected $primaryKey = 'id';
    public $companiesName;
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'requisites';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['fullname'], 'required'],
            [['company_id','default','inn', 'kpp', 'rs', 'ks', 'bik'], 'integer'],
            [['email'], 'email'],
            [['fullname','judadress', 'postadress', 'telfax', 'bank', 'ogrn', 'okpo', 'okogu', 'okvd','okato', 'ceostatus', 'ceo', 'ceoshort', 'ceoreason'], 'string', 'max' => 255],
        ];
    }
    public function attributeLabels()
    {
        return [
            'id' => 'ID',

            'telfax' => 'Телефон/факс',
            'fullname' => 'Полное наименование',
            'judadress' => 'Юридический адрес',
            'postadress' => 'Почтовый адрес',
            'email' => 'Электронная почта',
            'inn' => 'ИНН',
            'kpp' => 'КПП',
            'rs' => 'Рассчет',
            'ks' => 'Корсчет',
            'bik' => 'БИК',
            'bank' => 'Банк',
            'ogrn' => 'ОГРН',
            'okpo' => 'ОКПО',
            'okogu' => 'ОКОГУ',
            'okvd' => 'ОКВЭД',
            'okato' => 'ОКАТО',
            'ceostatus' => 'Должность руководителя',
            'ceo' => 'ФИО руководителя полностю',
            'ceoshort' => 'ФИО руководителя кратко',
            'ceoreason' => 'Основание руководителя',
            'default' => 'Флаг использования по умолчанию'
        ];
            }
    /**
     * {@inheritdoc}
     */


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


    /* Геттер для наименования компании */
    public function getCompaniesName() {
        return $this->Companies->name;
    }


}

masson
Сообщения: 545
Зарегистрирован: 2012.07.03, 15:59

Re: Как вывести в гриде поле из другой таблицы

Сообщение masson »

Пустая колонка не поэтому, а потому что нет данных. Надо проверить в дебаг панели какой запрос выполняется для выборки requisites. Если запрос правильный - выполнить его непосредственно в БД, может для строк которые выводятся в гриде реквизитов с default IS NULL физически в базе нет, или может они есть, но в них пустое поле telfax.

$model берется отсюда - https://www.yiiframework.com/doc/api/2. ... lue-detail
If this is an anonymous function, it will be called for each row and the return value will be used as the value to display for every data model. The signature of this function should be: function ($model, $key, $index, $column). Where $model, $key, and $index refer to the model, key and index of the row currently being rendered and $column is a reference to the yii\grid\DataColumn object.
Параметры подставляются на автомате из окружения. Их просто берешь и пользуешь внутри функции. Если $key, $index, $column внутри функции не нужны - определяешь функцию только с параметром $model.

Кстати в ActionColumn->buttons во вьюхе тоже косяк - https://www.yiiframework.com/doc/api/2. ... ons-detail
The callbacks should use the following signature: function ($url, $model, $key), where $url is the URL that the column creates for the button, $model is the model object being rendered for the current row, and $key is the key of the model in the data provider array.

Никакой dataProvider там не нужен. И кстати, гораздо удобнее использовать Xdebug вместо своих функций типа debug()
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: Как вывести в гриде поле из другой таблицы

Сообщение svil »

ОГРОМНОЕ СПАСИБО за подробный ответ. Изучаю.
Ответить