@marcio: Różne obiekty mogą mieć w takiej tabeli różne akcje, ponieważ przykładowo użytkownik może nie mieć praw do usunięcia części danych, część danych może nie być zdatna do generowania w PDF-ie itp.
Taka tabelka to wręcz książkowy przykład na to, gdzie można
sensownie zastosować taki bardzo popularny ostatnio wzorzec MVC. Na dobrą sprawę jest to przykład na to gdzie w ogóle jest miejsce tego wzorca. Ale o tym już było nie raz i nie ma sensu ciągnąć tego tutaj.

Zastanów się czego potrzebujesz. Potrzebujesz narzędzia uniwersalnego, które będzie w stanie przyjąć coś (konkretnie to implementację interfejsu, który sobie zdefiniujesz) co na podstawie jakiś tam informacji (np. filtry, paginacja) utworzy sobie kolekcję obiektów, które na końcu zostaną wyświetlone w jakiejś formie, np. tabelki. Narzędzie
musi być rozbudowane. Inaczej przy pierwszej próbie zrobienia czegoś niestandardowego polegnie i będzie przyczyną całej masy problemów do obejścia.
Tutaj piszę bez większego namysłu - Ty powinieneś zastanowić się czy aby na pewno takie rozwiązanie nie ma jakiś defektów, czy nie będzie ograniczać w jakiś skrajnych przypadkach itp. itd.
Pierwsze co będzie potrzebne to to coś co ma zwracać odpowiednią kolekcję obiektów do wyświetlenia. Interfejs tego będzie bardzo prosty (wybacz słabe nazewnictwo)<!--Geshi:281492:php--><pre class="php-brief" style="font-family:monospace;"><div class="head">
[topic=0]YPE</span> <span class="sy0">|</span> YouTube<span class="sy0">::</span><span class="me2">PLAYLIST_TYPE</span><span class="br0">)</span><span class="sy0">;</span></div><li class="li1"><div class="de1"> </div><li class="li2"><div class="de2"><span class="re0">$table</span><span class="sy0">-></span><span class="me1">setDataRepository</span><span class="br0">(</span><span class="re0">$data</span><span class="br0">)</span><span class="sy0">;</span></div>
[/list]<div class="foot">[PHP] [url="./Pobierz-Plik-281493.html"]plaintext[/url] </div></pre><!--/Geshi:281493:php-->Na dobrą sprawę takie rzeczy jak paginacja czy sortowanie również powinny być zrealizowane przy pomocy odpowiednich interfejsów, kolejno PaginableInterface (get/setOffset, get/setLimit) oraz SortableInterface (get/setField, get/setOrder lub inny interfejs get/setComparator).
To właściwie załatwia sprawę określenia co ma zostać pobrane. Następny etap to określenie co ma zostać wyświetlone. Można to zrobić w bardzo prosty sposób, tj. poprzez określenie etykiety (w przypadku tabelki będzie to nagłówek kolumny) oraz metody zwracającej wartość.[php]$table->addColumn('Tytuł', 'getTitle');
// Można by to zrobić też jako
$table->addColumn('Opis', 'description'); // spróbuje wywołać metodę getDescription albo isDescription (standardowe gettery)
// Czasami potrzeba zrobić coś bardziej dynamicznego, wtedy można by zastosować coś takiego:
$table->addColumn('Wielkość pliku', function($object) {
return FilesystemUtils::formatFileSize($object->getFileSize()); // zwraca przykładowo 15 KiB, 7,2 GiB, 244 b
});
// Albo nawet jako obiekt implementujący jakiś interfejs
Problem tego jakie konkretnie dane trzeba wyświetlać zdaje się również być rozwiązany. Kolejny problem to ustalenie jakie akcje (usuń, edytuj, drukuj, akceptuj itp.) mają być dostępne dla każdego obiektu. Takie akcje można również całkiem łatwo rozwiązać za pomocą obiektów, które będą implementowały prosty interfejs:
interface ActionInterface {
public function supports($object);
}
Metoda ta zwraca prawdę bądź fałsz w zależności od tego czy dany akcja jest dostępna dla danego obiektu, przykładowo akcje usuń i akceptuj mogłby wyglądać tak:
class RemoveAction implements ActionInterface {
private $user;
private $acl;
// konstruktur, get/set dla powyższych
public function supports($object) {
return $this->acl->hasPermissions($this->user, $object, ACL::REMOVE);
}
}
class ActivateAction implements ActionInterface {
public function supports($object) {
return $object instanceof ActivatableInterface && !$object->isActive();
}
}
Później takie akcje trzeba dodać tylko do tabelki:
$removeAction = new RemoveAction();
$removeAction->setUser($this->getCurrentUser());
$removeAction->setAcl($this->getAcl());
$activateAction = new ActivateAction();
$table->addObjectAction($removeAction);
$table->addObjectAction($activateAction);
Na koniec pozostaje kwestia ostatecznego wyrenderowania tabelki. Za to również odpowiedzialny jest osobny obiekt (bo przecież możesz chcieć wyrenderować tabelkę, listę, kolekcję w JS/JSON/XML czy jeszcze coś innego). Taki renderer to oczywiście również implementacja jakiegoś tam interfejsu, który definiuje jakieś tam metody.