Administrowanie wiadomościami ============== Administrowanie wiadomościami przede wszystkim odnosi się do wyświetlenia w liście wiadomości w widoku administratora co pozwala nam widzieć wiadomości o wszystkich statusach, aktualizować je oraz usuwać. Są one wykonywane odpowiednio przez operację `admin` oraz operację usuwania `delete`. Kod wygenerowany przez narzędzie `yiic` nie wymaga zbytniej modyfikacji. Poniżej wyjaśniamy przede wszystkim jak te dwie operacje zostały zaimplementowane. Wyświetlenie listy wiadomości w widoku tabelarycznym ----------------------------- Operacja `admin` wyświetla wszystkie wiadomości o wszystkich statusach w widoku tabelarycznym. Widok wspiera sortowanie oraz stronicowanie. Poniżej znajduje się metoda `actionAdmin()` kontrolera `PostController`: ~~~ [php] public function actionAdmin() { $model=new Post('search'); if(isset($_GET['Post'])) $model->attributes=$_GET['Post']; $this->render('admin',array( 'model'=>$model, )); } ~~~ Powyższy kod został wygenerowany przez narzędzie `yiic` i nie został zmodyfikowany. Najpierw tworzy on model wiadomości `Post` dla [scenariusza](/doc/guide/form.model) wyszukiwania `search`. Będziemy używać tego modelu do gromadzenia warunków wyszukiwania, które specyfikuje użytkownik. Jeżeli istnieją dane dostarczone przez użytkownika, przypisujemy je do modelu. Na koniec generujemy widok `admin` wraz z modelem. Poniżej znajduje się kod widoku `admin`: ~~~ [php] breadcrumbs=array( 'Manage Posts', ); ?>

Manage Posts

widget('zii.widgets.grid.CGridView', array( 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( array( 'name'=>'title', 'type'=>'raw', 'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)' ), array( 'name'=>'status', 'value'=>'Lookup::item("PostStatus",$data->status)', 'filter'=>Lookup::items('PostStatus'), ), array( 'name'=>'create_time', 'type'=>'datetime', 'filter'=>false, ), array( 'class'=>'CButtonColumn', ), ), )); ?> ~~~ Do wyświetlania wiadomości używamy klasy [CGridView]. Umożliwia ona nam sortowanie kolumn oraz wiadomości jeśli jest ich zbyt wiele by wyświetlić je na pojedynczej stronie. Nasza zmiana dotyczy sposobu wyświetlania każdej kolumny. Na przykład dla kolumny tytułu `title`, określamy iż powinna ona być wyświetlona jako hiperlink, który wskazuje na widok szczegółów wiadomości. Wyrażenie `$data->url` zwraca wartość właściwości `url`, którą zefiniowaliśmy w klasie wiadomości `Post`. > Tip|Wskazówka: Podczas wyświetlania tekstu wołamy metodę [CHtml::encode()] do zakodowania znajdujących się w nim wpisów HTML. Chroni to przed [atakami XSS](http://www.yiiframework.com/doc/guide/topics.security). Usuwanie wiadomości -------------- W każdym wierszu siatki danych administratora `admin` znajduje się przycisk usuwania. Kliknięcie w ten przycisk powinno usunąć odpowiednią wiadomość. W aplikacji wywołuje to wywołanie akcji `delete` zaimplementowanej w następujący sposób: ~~~ [php] public function actionDelete() { if(Yii::app()->request->isPostRequest) { // we only allow deletion via POST request $this->loadModel()->delete(); if(!isset($_GET['ajax'])) $this->redirect(array('index')); } else throw new CHttpException(400,'Invalid request. Please do not repeat this request again.'); } ~~~ Powyższy kod został wygenerowany przez narzędzie `yiic` i nie został zmieniony. Będziemy chcieli wyjaśnić nieco więcej na temat sprawdzania `$_POST['ajax']`. Widżet [CGridView] posiada bardzo fajną funkcję, która domyślnie wykonuje operacje sortowania, stronicowania, usuwania przy użyciu trybu AJAX. Oznacza to, że cała strona nie jest przeładowywana jeśli jakakolwiek z ww. operacji jest wykonywana. Jednakże, istnieje również możliwość uruchamiania widżetu bez trybu AJAX (poprzez ustawienie właściwości `ajaxUpdate` na false albo poprzez wyłączenie obsługi JavaScript po stronie klienta). Dla akcji `delete` zachodzi konieczność rozróżnienia tych dwóch scenariuszy: jeśli żądanie usuwania pochodzi z AJAX-a nie powinniśmy przekierowywać przeglądarki użytkownika, w przeciwnym przypadku powinniśmy. Usuwanie wiadomości powinno również spowodować usuwanie jej wszystkich komentarzy. Dodatkowo powinniśmy również zaktualizować tabelę `tbl_tag` uwzględniając tagi z usuniętej wiadomości. Oba powyższe zadania powinny zostać osiągnięte poprzez napisanie metody `afterDelete` w klasie modelu wiadomości `Post` w następujący sposób: ~~~ [php] protected function afterDelete() { parent::afterDelete(); Comment::model()->deleteAll('post_id='.$this->id); Tag::model()->updateFrequency($this->tags, ''); } ~~~ Powyższy kod jest bardzo prosty. Najpierw usuwane są wszystkie komentarze, których `post_id` jest takie same jak ID usuniętej wiadomości. Następnie aktualizowana jest tabela `tbl_tag` dla wartości tagów `tags` z usuniętej wiadomości. > Tip|Wskazówka: Musimy jawnie usunąć wszystkie komentarze dla usuniętej wiadomości, ponieważ SQLite nie wspiera ograniczeń klucza obcego. W silnikach bazy danych, które wpierają ograniczanie (takich jak MySQL, PostgreSQL), ograniczenie klucza obcego może zostać tak zdefiniowane, że silnik bazy danych automatycznie usunie powiązane komentarze w momencie usuwania wiadomości. W takim przypadku nie będziemy potrzebowali w naszym kodzie jawnego usuwania.
$Id: post.admin.txt 3557 2012-02-09 15:26:05Z alexander.makarow $