filtrare un CActiveDataPRovider in base ad una chiave esterna?

Ho una tabella News in cui ho inserito questa relazione:




  public function relations() {

    // NOTE: you may need to adjust the relation name and the related

    // class name for the relations automatically generated below.

    return array(

        'categorie' => array(self::MANY_MANY, 'Categorie', 'CategoryAssignment(news,categoria)'),

    );

  }

Vorrei che alla richiesta index.php?r=news/index&id=33, comparissero tutte quelle news che hanno la categoria 33. Non mi riesce =(.

Riesco a mostrare, per ogni News, i tags assegnati:




  <?php if (count($data->categorie) > 0): ?>

    <div align="right">

      <b>tags:</b>

      <?php foreach ($data->categorie as $item) : ?>

        <?php echo $item->nome; ?>

      <?php endforeach; ?>

    </div>

  <?php endif; ?>

Ho provato nel controller actionIndex delle News a fare questo:




  public function actionIndex() {

    $dataProvider = new CActiveDataProvider('News',array(

        'criteria' => array (

            'with' => 'categorie',

            'condition' => 'categorie.id=3',

        )

    ));

    $this->render('index', array(

        'dataProvider' => $dataProvider,

    ));

  }

Ma tutto quello che ottengo è questo:


Error 500


CDbCommand ha riportato un errore nell'esecuzione della query SQL: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'categorie.id' in 'where clause'

Qualcuno sa spiegarmi il perchè?

Invece di fare le 3 in discoteca, faccio le 3 davanti al pc. Molto bene … se non che, dopo aver passato un pomeriggio sbattendo la testa su questo problema… poco fa mi si è accesa una lampadina. Così sono andato nella pagina delle categorie ed in ogni categoria, mostro tutte le news ad essa associate.

Continuo a non comprendere come mai non riesco a filtrare tutte le news che hanno una certa categoria. Ho risolto il problema, ma non vedo l’ora di avere totale padronanza sul Model di Yii. Oggi non ne ho.

Posso chiederti il significato di


CategoryAssignment(news,categoria)

?

Edit.

Mi sono letto la documentazione e penso di aver capito che tu hai una tabella CategoryAssignment con due colonne, news e categoria. Giusto?

Ho avuto difficoltà a capire perché io ho sempre scritto un db seguendo le convenzioni che Yii stesso suggerisce: http://www.yiiframework.com/doc/guide/1.1/en/basics.convention

Comunque credo di aver trovato la soluzione, dopo ti riscrivo.

Non ne sono sicuro, ma prova così:


$dataProvider = new CActiveDataProvider('News',array(

        'criteria' => array(

            'with' => array(

                'categorie',

                'condition' =>'categorie.id=3

            )

        )

    ));

In ogni caso se la soluzione qui sopra non dovesse funzionare potresti fare semplicemente:




$model = Categorie::model()->findByPk(3);


$dataProvider = new CActiveDataProvider($model, array(

        'criteria' => array(

            'with' => array('news')

        )

    ));




In questo caso ti conviene impostare nelle relazioni del model Categorie




'news' => array(

                self::BELONGS_TO, 'News', 'id', 'together'=>false

            ),



Together su false è utile in questi casi perché ad una sola categoria sono associate più news, e le performance calano se devi fare una query grossa che ti va a recuperare sempre categoria-news.

Invece in questo modo vengono fatte 2 query distinte e sei apposto, in teoria :P

Ciao,

puoi mostrare la struttura delle due tabelle news e categorie?

Aggiungo anche… può esserti utile questo??

A me si =). Cioè, mi servirebbe eccome: avrei il paginatore per tutte le news di una determinata categoria.


DROP TABLE IF EXISTS `Categorie`;

CREATE TABLE IF NOT EXISTS `Categorie` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `nome` varchar(128) NOT NULL,

  PRIMARY KEY (`id`)

) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;


DROP TABLE IF EXISTS `CategoryAssignment`;

CREATE TABLE IF NOT EXISTS `CategoryAssignment` (

  `categoria` int(11) NOT NULL,

  `news` int(11) NOT NULL,

  `id` int(11) NOT NULL AUTO_INCREMENT,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;


DROP TABLE IF EXISTS `News`;

CREATE TABLE IF NOT EXISTS `News` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `attiva` tinyint(1) NOT NULL,

  `datainserimento` date NOT NULL,

  `titolo` varchar(128) NOT NULL,

  `abstract` text NOT NULL,

  `corpo` text NOT NULL,

  `datainiziovalidita` date NOT NULL,

  `datafinevalidita` date NOT NULL,

  `pubblicainvetrina` tinyint(1) NOT NULL,

  `pubblica` tinyint(1) NOT NULL DEFAULT '0',

  PRIMARY KEY (`id`)

) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

Solo che vorrei farlo dalla pagina delle news.

Dovresti fare cosi:


 public function actionIndex() {

    $dataProvider = new CActiveDataProvider('News',array(

        'criteria' => array (

            'with' => 'categorie',

            'condition' => 't1.id=3',

        )

    ));

    $this->render('index', array(

        'dataProvider' => $dataProvider,

    ));

  }

Yii da automaticamente gli alias: t per la tabella principale, t1 per la prima tabella collegata, t2 per la seconda eccetera eccetera.

Oppure puoi impostare l’alias che preferisci:




  public function actionIndex() {

    $dataProvider = new CActiveDataProvider('News',array(

        'criteria' => array (

            'with' => 'categorie',

            'alias' => 'categorie',

            'condition' => 'categorie.id=3',

        )

    ));

    $this->render('index', array(

        'dataProvider' => $dataProvider,

    ));

  }