Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [OPT 1.1.5] Jakie interfejsy dla obiektu aby mógł być iterowany w section jak array?
tornax
post
Post #1





Grupa: Zarejestrowani
Postów: 25
Pomógł: 0
Dołączył: 11.10.2006

Ostrzeżenie: (0%)
-----


Mam problem z iterowaniem w OPT 1.1.5 obiektów które mają się zachowywać jak tablice (array).

(Narazie nie zamiejszczam wszystkich definicji klas ponieważ to zazwyczaj odstrasza od dalszego czytania)

Mam klasę która ma taki oto nagłówek
  1. class ormcollection implements SeekableIterator, ArrayAccess, Countable

oraz kawałek kodu który zwraca obiekt tej klasy (linijka 1.) oraz ładuje do odpowiedniej sekcji w templatce (linijka 2.)
  1. $data = configurator::finder()->getAll();
  2. $this->view->assign('configurator', $data);

obiekt $data (klasa ormcollection) przechowywuje w prywatnej tablicy obiekty klasy configurator, które odzwierciedlają poszczególne rekordy w bazie danych
  1. class configurator extends orm {
  2.  
  3. public $name;
  4. public $active = 0;
  5.  
  6. public function __construct(){
  7. parent::__construct('configurator');
  8. }
  9.  
  10. public static function finder($className=__CLASS__){
  11. return parent::finder($className);
  12. }
  13. }

Teraz templatka wygląda do tego banalnie
  1. {section=configurator}
  2. {$configurator.name}
  3. {/section}

... ale nic nie generuje ... więc dla sprawdzenia czy działa iteracja i są pobierane dane wrzuciłem pare linijek do testu
  1. $data = configurator::finder()->getAll();
  2.  
  3. var_dump('foreach');
  4. foreach($data as $r){
  5. var_dump($r['name'], $r->name);
  6. }
  7.  
  8. var_dump('for');
  9. for($i=0; $i < count($data); $i++){
  10. var_dump($data[$i]['name'], $data[$i]->name);
  11. }
  12.  
  13. $this->view->assign('configurator', $data);

z wynikiem
  1. string(7) "foreach"
  2. string(10) "Deskorolki"
  3. string(10) "Deskorolki"
  4. string(12) "Poduszkowiec"
  5. string(12) "Poduszkowiec"
  6. string(3) "for"
  7. string(10) "Deskorolki"
  8. string(10) "Deskorolki"
  9. string(12) "Poduszkowiec"
  10. string(12) "Poduszkowiec"

Iteracja działa i zwraca wyniki ale nie w OPT, aby upewnić się, że samo OPT działa wykonałem taki test
  1. $this->view->assign('configurator', array(array('name'=>'pies'), array('name'=>'kot')));

rezultat
  1. pieskot

Test co prawda na tablicach ale przynjmniej wiem, że przekazuje zmienne. Moje podejżenie jest takie, że w ormcollection brakuje jakiegoś dodatkowego interfejsu ale nie potrafię powiedzieć jakiego bo ze wszystkimi obecnymi pętle for i foreach działąją bez problemu.

Czy ktoś ma może jakiś pomysł ?
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
Zyx
post
Post #2





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Tak, gałąź 2.x została przepisana całkowicie od nowa (m.in. po to, by wyeliminować tego typu idiotyzmy, z którymi teraz się męczysz) i nie jest kompatybilna ani pod kątem API, ani pod kątem języka szablonów.

Ogólnie kody instrukcji możesz znaleźć w pliku opt.instruction.php. Każda instrukcja ma własną klasę, gdzie obsługiwana jest kompilacja poszczególnych znaczników do kodu PHP. Klasa optSection jest gdzieś na początku tego pliku. To, co Ci jest najbardziej potrzebne, znajduje się w metodzie showAction(). Najważniejszy kod to te linijki:

  1. if(is_null($state))
  2. {
  3. $output .= ' if(is_array('.$link.') && ($__'.$name.'_cnt = sizeof('.$link.')) > 0){ ';
  4. }
  5. else
  6. {
  7. if($this -> tpl -> statePriority == OPT_PRIORITY_NORMAL)
  8. {
  9. $output .= ' if('.$state.' && is_array('.$link.') && ($__'.$name.'_cnt = sizeof('.$link.')) > 0){ ';
  10. }
  11. else
  12. {
  13. $output .= ' if('.$state.'){ if(is_array('.$link.') && ($__'.$name.'_cnt = sizeof('.$link.')) > 0){ ';
  14. }
  15. }


Jak widzisz, odpowiadają one za wygenerowanie kodu PHP sprawdzającego typ i zliczającego elementy tablicy. Musisz je zastąpić tak, aby akceptowały też obiekty implementujące odpowiednie interfejsy. Na wszelki wypadek radzę Ci też poprawić trochę linijek powyżej - nie wiem, czy korzystasz z sekcji dynamicznych, ale na wszelki wypadek popraw i je, gdyby ktoś miał to jeszcze rozwijać, by w Ciebie gromami nie rzucał (IMG:style_emoticons/default/smile.gif) .

Po tym zabiegu musisz jeszcze skoczyć do sectionBegin() i poprawić tam jedną drobną rzecz:

  1. if($this->sections[$this->nesting]['order'] == 'reversed')
  2. {
  3. $this -> compiler -> out(' for($__'.$name.'_id = $__'.$name.'_cnt - 1; $__'.$name.'_id >= 0; $__'.$name.'_id--){ $__'.$name.'_val = &'.$this->sections[$this->nesting]['link'].'[$__'.$name.'_id]; ');
  4. }
  5. else
  6. {
  7. $this -> compiler -> out(' foreach('.$this->sections[$this->nesting]['link'].' as $__'.$name.'_id => &$__'.$name.'_val){ ');
  8. }


Jak widzisz, do wyświetlania sekcji w odwróconej kolejności wykorzystywana jest pętla for, zatem jeśli korzystasz z tego, dobrze by było implementować ArrayAccess. Z kolei dla porządku normalnego jest foreach, tylko tam przy generowaniu zmiennej wartości OPT wstawia brzydki znaczek referencji, który nie bardzo będzie chciał współpracować z Twoimi obiektami. Usuwasz go i problem załatwiony. Identyczny symbol masz też przy pętli for.

Generalnie jak chcesz sekcje odwrócone, możesz zastosować myk, który zaimplementowałem w formacie Objective do OPT 2.0. Tam najpierw jedziemy pętlą foreach po iteratorze i budujemy tablicę wartości. Następnie ją odwracamy i wprowadzamy do właściwej pętli. Może zbyt efektywne to nie jest, ale dla ogólnego przypadku jest to jedyna metoda. Ewentualnie, skoro już robisz konkretne obiekty, możesz tu zaimplementować to, co Ci najbardziej pasuje.

Ten post edytował Zyx 25.02.2011, 22:06:42
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 27.12.2025 - 20:48