Yii 2 Как отфильтровать записи по связи многие ко многим?

У меня есть есть таблица устройства(device) и есть таблица список датчиком(SensorsList), связаные через таблицу датчики(sensors), список устройст выводиться с имеющимеся у него датчиками, но я не могу сделать фильтрацию до датчикам

При попытке фильтрации выдаёт ошибку введите сюда описание изображения при попытке найти похожую ошибку находил только решение чрез viaTable но мне оно не подходит Контролер:

<?php

namespace frontend\controllers;

use frontend\models\Device;
use frontend\models\SearchDevice;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;

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

    /**
     * Lists all Device models.
     *
     * @return string
     */
    public function actionIndex()
    {
        $searchModel = new SearchDevice();
        $dataProvider = $searchModel->search($this->request->queryParams);
        $dataProvider->pagination->pageSize = 15;

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

    /**
     * Displays a single Device model.
     * @param int $id ID
     * @return string
     * @throws NotFoundHttpException if the model cannot be found
     */
    public function actionView($id)
    {
        $temperatures = Device::find()->where(['id' => $id])->one()->getTemperature()->asArray()->all();
        $humidities = Device::find()->where(['id' => $id])->one()->getHumidity()->asArray()->all();
        
        return $this->render('view', [
            'model' => $this->findModel($id),
            'temperatures' => $temperatures,
            'humidities' => $humidities
        ]);
    }

    /**
     * Creates a new Device model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return string|\yii\web\Response
     */
    public function actionCreate()
    {
        $model = new Device();

        if ($this->request->isPost) {
            if ($model->load($this->request->post()) && $model->save()) {
                return $this->redirect(['view', 'id' => $model->id]);
            }
        } else {
            $model->loadDefaultValues();
        }

        return $this->render('create', [
            'model' => $model,
        ]);
    }

    /**
     * Updates an existing Device model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param int $id ID
     * @return string|\yii\web\Response
     * @throws NotFoundHttpException if the model cannot be found
     */
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ($this->request->isPost && $model->load($this->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        }

        return $this->render('update', [
            'model' => $model,
        ]);
    }

    /**
     * Deletes an existing Device model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param int $id ID
     * @return \yii\web\Response
     * @throws NotFoundHttpException if the model cannot be found
     */
    public function actionDelete($id)
    {
        $this->findModel($id)->delete();

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

    /**
     * Finds the Device model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param int $id ID
     * @return Device the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id)
    {
        if (($model = Device::findOne(['id' => $id])) !== null) {
            return $model;
        }

        throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
    }
}

Модель устройств:

<?php

namespace frontend\models;

use Yii;

/**
 * This is the model class for table "device".
 *
 * @property int $id
 * @property string|null $device_name
 * @property int $user_id
 *
 * @property Humidity[] $humidities
 * @property Sensors[] $sensors
 * @property Temperature[] $temperatures
 * @property User $user
 */
class Device extends \yii\db\ActiveRecord
{
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'device';
    }


    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['user_id'], 'required'],
            [['user_id'], 'integer'],
            [['device_name'], 'string', 'max' => 255],
            [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id'],],
            
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'device_name' => 'Назва пристрою',
            'user_id' => 'Користувач',
            'deviceSensors' => 'Датчики'
        ];
    }

    /**
     * Gets query for [[Humidities]].
     *
     * @return \yii\db\ActiveQuery
     */
    public function getHumidities()
    {
        return $this->hasMany(Humidity::className(), ['device_id' => 'id']);
    }

    /**
     * Gets query for [[Sensors]].
     *
     * @return \yii\db\ActiveQuery
     */
    public function getSensors()
    {
        return $this->hasMany(Sensors::className(), ['device_id' => 'id']);
    }

    /**
     * Gets query for [[Temperatures]].
     *
     * @return \yii\db\ActiveQuery
     */
    public function getTemperatures()
    {
        return $this->hasMany(Temperature::className(), ['device_id' => 'id']);
    }

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

    public function getDeviceSensors(){
        $deviceSensors = "";
        foreach ($this->sensors as $key=>$sensor){
            $deviceSensors .= $sensor->sensor->name . "<br>";
        }
        return $deviceSensors;
    }
}

Вывод устройств:

<?php

use yii\helpers\Html;
use yii\helpers\Url;
use yii\grid\ActionColumn;
use yii\grid\GridView;
use frontend\components\cache\DbDependencyHelper;
use frontend\models\Device;
use frontend\models\Sensors;
use frontend\models\SensorsList;
use frontend\models\User;
use yii\base\Model;
use yii\helpers\ArrayHelper;

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

$this->title = Yii::t('app', 'Пристрої');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="device-index">

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

    <p>
        <?= Html::a(Yii::t('app', 'Create Device'), ['create'], ['class' => 'btn btn-success']) ?>
    </p>
    <?php echo $this->render('_search', ['model' => $searchModel]); ?>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            'id',
            'device_name',
            [
                'attribute' => 'deviceSensors',
                'format' => 'html',
                'filter' => ArrayHelper::map(SensorsList::find()->all(), 'id', 'name'),
                //Html::activeDropDownList($searchModel, 'sensors', ArrayHelper::map(SensorsList::find()->asArray()->all(), 'id', 'name'),['class'=>'form-control','prompt' => 'Select Category', 'multiple' => true, ]),
            ],
            [
                'class' => ActionColumn::className(),
                'urlCreator' => function ($action, $model, $key, $index, $column) {
                    return Url::toRoute([$action, 'id' => $model->id]);
                }
            ],
        ],
    ]); ?>
    <? ?>

</div>

Поиск

<?php

namespace frontend\models;

use yii\base\Model;
use yii\data\ActiveDataProvider;
use frontend\models\Device;

/**
 * SearchDevice represents the model behind the search form of `frontend\models\Device`.
 */
class SearchDevice extends Device
{
    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['id', 'user_id'], 'integer'],
            [['device_name', 'deviceSensors'], 'safe'],
        ];
    }

    /**
     * {@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 = Device::find();
        $query = Device::find()->joinWith(['sensors.sensor', 'user']);
        // add conditions that should always apply here

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        

        foreach($this->rules() as $rulesArray){
            foreach($rulesArray as $ruleSecondLevel){
                if(is_array($ruleSecondLevel)){
                    foreach($ruleSecondLevel as $field){
                        $dataProvider->sort->attributes[$field]= [
                            'asc' => [$field => SORT_ASC],
                            'desc' => [$field => SORT_DESC],
                        ];
                    }
                }
            }
        }
       // var_dump($dataProvider);die;
        $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' => $this->id,
            'user_id' => $this->user_id,
            //'deviceSensors' => $this->getSensors(),

        ]);

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

        return $dataProvider;
    }
}


Ответы (0 шт):