Przekazanie wartości przez url do CDbCriteria

Witam.

Styworzyłem portlet, który w widoku


http://....../pobrania/index.php

wyświetla w bocznym div’ie odpowiednią listę z kategoriami pobrań. Standardowo po odpaleniu widoku widoczne są wszystkie rekordy (i to jest OK) we wszystkich kategoriach. Portlet ma służyć jako filtr.

W modelu pobrania dodałem:




public function getUrl2()

    {

        return Yii::app()->createUrl('pobrania/index2', array(

            'category'=>$this->typpobrania_id,

        ));

    }


public function search2()

	{

		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);

		$criteria->compare('nazwa',$this->nazwa,true);

		$criteria->compare('file',$this->file,true);

		$criteria->compare('create_time',$this->create_time);

		$criteria->compare('update_time',$this->update_time);

		$criteria->condition = "typpobrania_id = 2";

		

		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}



W kontrolerze pobrania dodałem:





public function actionIndex2()

	{

		$model=new Pobrania('search2');


		$model->unsetAttributes(); 

		if(isset($_GET['Pobrania']))

			$model->attributes=$_GET['Pobrania'];

 

				

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

			'dataProvider'=>$model->search2(),

			'model'=>$model)

		);

	}



  • uprawnienia do "index2" w public function accessRules()

Stworzyłem w widoku pobrania plik index2.php ze standardową zawartością:




<?php

$this->breadcrumbs=array(

	'Pobrania',

);


$this->menu=array(

	array('label'=>'Dodaj pobranie', 'url'=>array('create')),

	array('label'=>'Zarządzaj pobraniami', 'url'=>array('admin')),

);




?>


<h1>Pobrania</h1>


<?php $this->widget('zii.widgets.CListView', array(

	'dataProvider'=>$dataProvider,

	'itemView'=>'_view',

)); ?>



Rzecz polega na tym, iż kiedy kliknę na pozycję z listy portletu to przybiera ona postać:




http://......./index.php?r=pobrania/index2&category=2



i teraz chodzi o to aby wartość parametru "category" przekazać do modelu do funkcji search2() w miejsce $criteria->condition = "typpobrania_id = 2";, aby lista wyświetlanych pozycji była dynamiczna w zależności od tego którą pozycję kliknę z portletu.

W przypadku kiedy mam jak teraz na stałe zdefiniowaną wartość parametru "category" to co kolwiek kliknę to oczywiście zawsze dostaje to samo.

Próbowałem z "$_GET", ale chyba coś nie tak.

Ale to skomplikowanie zrobiłeś…

Nie potrzebny widok index2, ani funkcja search2…

  1. W kontrolerze dajesz:



public function actionIndex($category='')

        {

...

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

                        'dataProvider'=>$model->search($category),

                        'model'=>$model)

                );



Tutaj jako opcjonalny parametr jest $category. Jak nie podasz tego parametru i wywołasz samo "pobrania/index" to też zadziała! :slight_smile:

  1. W modelu:



public function search($category)

        {

...

                if(!empty($category)) $criteria->condition = "typpobrania_id = ".(int)$category;

                

                return new CActiveDataProvider($this, array(

                        'criteria'=>$criteria,

                ));

        }



I tyle :slight_smile: Powinno działać tak jak chcesz.

Problem rozwiązany. Okazało się, że trochę namieszałem.

  1. Portlet wyświetlał co jest do pobrania zamiast nazw kategorii pobrań.

  2. Namieszałem w kodzie.

Odp.

ad 1. Poprawiłem portlet

/protected/components/DownloadCategory.php




<?php

Yii::import('zii.widgets.CPortlet');

 

class DownloadCategory extends CPortlet

{

    public $title='Kategoria';

     

    public function getDownloadCategory()

    {

        return TypPobrania::model()->findDownloadCategory();

    }

 

    protected function renderContent()

    {

        $this->render('downloadCategory');

    }

}

?>



/protected/components/views/downloadCategory.php




<ul>

	<?php foreach($this->getDownloadCategory() as $downloads): ?>

	<li> <?php echo CHtml::link(CHtml::encode($downloads->nazwa), $downloads->getUrl2()); ?> </li>

	<?php endforeach; ?>

</ul>



ad 2. Poprawiłem modele

Model Pobrania




public function getUrl2()

    {

        return Yii::app()->createUrl('pobrania/index2', array(

            'category'=>$typpobrania->id,

        ));

		

    }


public function search2()

	{

		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);

		$criteria->compare('nazwa',$this->nazwa,true);

		$criteria->compare('file',$this->file,true);

		$criteria->compare('create_time',$this->create_time);

		$criteria->compare('update_time',$this->update_time);

		$criteria->condition = "typpobrania_id =".$_GET['category'];

		

		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}




Usunąłem funkcję function findDownloadCategory() bo była zbyteczna.

Model TypPobrania - dodałem




public function findDownloadCategory()

    {

        return $this->findAll();

    }

	

	public function getUrl2()

    {

        return Yii::app()->createUrl('pobrania/index2', array(

            'category'=>$this->id,

        ));

		

    }



Teraz kod pewnie będzie Ci działał, ale…

W modelu nie używamy zmiennych pobieranych z tablic $_GET i $_POST itp…

Model musi być uniwersalny, ponieważ może być wykorzystywany np. w aplikacji konsolowej.

Także lepszy sposób jest ten, który podałem Ci wyżej (w funkcji search dodać zmienną, i w kontrolerze pobierać jej wartość z $_GET).

Thx, sprawdzę.

Może banalne, ale za nic nie mogę pobrać do modelu danych z GET’a do funkcji search2().

Cały czas wyrzuca mi błąd braku wartości do kwerendy?

Adres url to http://…/index.php?r=pobrania/index2&category=1, więc GET powinien przechować 1 a tu nic, jak wpisze na sztywno 1 to działa.




CDbCommand nie zdołał wykonać instrukcji SQL: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1. The SQL statement executed was: SELECT COUNT(*) FROM `tbl_pobrania` `t` WHERE typpobrania_id = 



Więc moje pytanie jak to odebrać i przesłać do modelu.

Czy tak wygląda Twoja deklaracja akcji index2 w kontrolerze?




public function actionIndex2($category='')



Tak wogóle to możesz podrzucić całą metodę actionIndex2 i całą metodę search2

Zrobiłem tak jak proponowałeś. Działa tak jak trzeba, dodałem jeszcze zmianę w widoku admin.php w zii.widgets.grid.CGridView aby uwzględniało zmienną $category z funkcji search()na:




'dataProvider'=>$model->search($category),



Nawet nie będę pisał o błędach bo wstyd (chyba przyzwyczajenie do starego sposobu), ale tak ogólnie walnąłem byka i funkcji actionIndex i search().

Dzięki za wytrwałość.

nie za duzo kombinacji z ta dodatkowa funkcja search2 i dodatkowymy parametrami do search()?

jak rozumiem pole "typpobrania_id" to atrybut modelu (i kolumna w tabeli), wiec wystarczylo w akcji przypisac wartosc przekazana GET do atrybutu i uzyc standardowej funkcji search(), ktora domyslnie filtruje po wszystkich ustawionych atrybutach (no chyba, ze standardowa funkcja search zostala zmodyfikowana i filtrowanie po akurat tej kolumnie zostalo zniej usuniete)… Moim zdaniem poza akcją (przyklad ponizej) nie trzeba modyfikowac nic w modelu.




public function actionIndex($category=null) {

   ...

   $model->typpobrania_id = $category;

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

        'dataProvider'=>$model->search(),

        'model'=>$model)

   );



Obydwa sposoby (od Mariusz W. i redguy), które bazują na standardowych funkcjach actionIndex() i search() działają poprawnie - sprawdzone i wdrożone.

Dzięki za wyjaśnienia i pomoc. :)