Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Wywoływanie metody tylko z zewnątrz, Tak żeby klasa metody nie mogła jej wywołać
starach
post 13.12.2008, 04:20:18
Post #1





Grupa: Zarejestrowani
Postów: 999
Pomógł: 30
Dołączył: 14.01.2007
Skąd: wiesz ?

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


Właśnie ponad 2 godziny spędziłem na odpluskwianiu mojego fw z debilnego błędu.
Mój Loader który zajmuje się wywoływanie kontrolera, ma też za zadanie pobrać z niego widok i model. Po czym wykonać model i wrzucić wynik do widoku. Oczywiście inteligentnie w celach testowych napisałem jedną cholerną linijkę w widoku ( dodawanie danych ) żeby sprawdzić czy wyświetli. Tak wiem błąd logiczny architektury MVC, ale to miał być tylko test. W efekcie Loader nadpisywał mi oczywiście dane i nie wiedziałem dlaczego. sciana.gif

Czy da się w jakiś magiczny sposób zablokować wywoływanie metody z klasy w której ona się znajduje?
W tym wypadku chciałbym żeby klasa SDL_View nie miała dostępu do swojej metody assign(). Oczywiście po południu przeprogramuję metody dzieląc je na assign() które będzie dodawało dane do istniejących i clear() które je będzie czyściło, ale tak czy siak dobrze by było to wywołanie zablokować.

Sorry za to masło maślane powyżej ale już ledwo na oczy patrzę.
Go to the top of the page
+Quote Post
mike
post 13.12.2008, 09:38:31
Post #2





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

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


Zamiast brnąć z jednych głupich pomysłów w kolejne przepisz to od nowa.
Przecież to co opisujesz to jakiś spaghetti code.
Go to the top of the page
+Quote Post
SirZooro
post 13.12.2008, 10:23:59
Post #3





Grupa: Zarejestrowani
Postów: 243
Pomógł: 32
Dołączył: 14.06.2007

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


Jedyne rozwiązanie które mi się nasuwa to umieszczenie metody w klasie bazowej jako metody prywatnej.


--------------------
Go to the top of the page
+Quote Post
phpion
post 13.12.2008, 10:29:00
Post #4





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(SirZooro @ 13.12.2008, 12:23:59 ) *
Jedyne rozwiązanie które mi się nasuwa to umieszczenie metody w klasie bazowej jako metody prywatnej.

Autorowi chyba chodzi o coś dokładnie odwrotnego: zablokowanie wywołania metody z klasy, a umożliwienie wywołania tylko z zewnątrz. Osobiście nie mam pojęcia jak to zrobić (o ile jest to oczywiście w ogóle możliwe).
Go to the top of the page
+Quote Post
Morkai
post 13.12.2008, 14:09:40
Post #5





Grupa: Zarejestrowani
Postów: 24
Pomógł: 3
Dołączył: 25.08.2005

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


Da się to uzyskać poprzez odpowiednie obrobienie wyniku debug_backtrace()" title="Zobacz w manualu PHP" target="_manual, ale sensu podobnie jak mike nie widzę winksmiley.jpg

  1. <?php
  2.  
  3. function check_caller()
  4. {
  5.    $backtrace = debug_backtrace();
  6.    
  7.    if (!isset($backtrace[2]) || ($backtrace[1]['class'] === (isset($backtrace[2]['class']) ? $backtrace[2]['class'] : null)))
  8.    {
  9.        throw new BadMethodCallException();
  10.    }
  11. }
  12.  
  13. ?>


Użycie
  1. <?php
  2.  
  3. class Foo
  4. {
  5.    function doSmth()
  6.    {
  7.        $this->doFoo();
  8.    }
  9.    
  10.    function doFoo()
  11.    {
  12.        check_caller();
  13.        
  14.        echo __FUNCTION__, "\n";
  15.    }
  16. }
  17.  
  18. class Bar
  19. {
  20.    private $foo;
  21.    
  22.    function __construct(Foo $foo)
  23.    {
  24.        $this->foo = $foo;
  25.    }
  26.    
  27.    function doBar()
  28.    {
  29.        $this->foo->doFoo();
  30.    }
  31. }
  32.  
  33. function do_baz(Foo $foo)
  34. {
  35.    $foo->doFoo();
  36. }
  37.  
  38. $foo = new Foo();
  39. $bar = new Bar($foo);
  40.  
  41. echo '<pre>';
  42. try { $foo->doFoo(); } catch (BadMethodCallException $x) { echo $x, "\n"; }
  43. try { $foo->doSmth(); } catch (BadMethodCallException $x) { echo $x, "\n"; }
  44. try { $bar->doBar(); } catch (BadMethodCallException $x) { echo $x, "\n"; }
  45. try { do_baz($foo); } catch (BadMethodCallException $x) { echo $x, "\n"; }
  46. echo '</pre>';
  47.  
  48. ?>
Go to the top of the page
+Quote Post
starach
post 13.12.2008, 15:41:11
Post #6





Grupa: Zarejestrowani
Postów: 999
Pomógł: 30
Dołączył: 14.01.2007
Skąd: wiesz ?

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


Cytat(mike @ 13.12.2008, 09:38:31 ) *
Zamiast brnąć z jednych głupich pomysłów w kolejne przepisz to od nowa.
Przecież to co opisujesz to jakiś spaghetti code.
  1. <?php
  2. final class DRA_Loader_Module_Collection extends SDL_Collection
  3. {
  4.    /**
  5.      * Appends new value
  6.      * @param DRA_Loader_Module $module
  7.      */
  8.    public function append(DRA_Loader_Module $module)
  9.    {
  10.        $this->_append($module);
  11.    }
  12.    /**
  13.      * Runs all modules controllers
  14.      */
  15.    public function init()
  16.    {
  17.        foreach($this as $module)
  18.        {
  19.            /* @var $module DRA_Loader_Module */
  20.            if($module->doTrigger())
  21.            {
  22.                $module->getObject()->init();
  23.                
  24.                $view = $module->getObject()->view();
  25.                $model = $module->getObject()->model();
  26.                // Check if required objects are correct
  27.                if(!is_object($model) || !DRA_Class::doesImplements($model, array('SDLi_Model')))
  28.                {
  29.                    throw new Error('LOADER_MODULE_MODEL_INCORRECT', array('model' => get_class($model)));
  30.                }
  31.                if(!is_object($view) || !DRA_Class::doesImplements($view, array('SDLi_View', 'SDLi_Initializable')))
  32.                {
  33.                    throw new Error('LOADER_MODULE_VIEW_INCORRECT', array('view' => get_class($view)));
  34.                }
  35.  
  36.                $view->init();
  37.  
  38.                // Gather data from Model and assign them to view
  39.                $view->assign($model->perform());
  40.                // Create new website main frame and assign view output to it
  41.                $frame = new DRA_Website_Frame();
  42.                $frame->setId(DRA_Website_Frame::CENTER);
  43.                $frame->setContent($view->create());
  44.                DRA_Engine::website()->frames()->append($frame);
  45.            }
  46.        }
  47.    }
  48. }
  49. ?>
Skoro to jest spaghetti code to dlaczego wiesz co tutaj się dzieje bez większego opisywania tego mike? tongue.gif
DRA_Loader pobiera przetworzony url z DRA_Router i w ten sposób ustala klasę kontrolera głównego którą zapisuje w tej kolekcji.

@Morkai: Też myślałem o debug_backtrace ale mam dziwne wrażenie że tego sposobu zastosować nie należy. Tylko cholera jakoś uzasadnienia nie mogę znaleźć. Chyba tylko mogę się podeprzeć spadkiem wydajności. Bo MVC zamierzam stosować też we wtyczkach a co za tym idzie klasę SDL_View implementującą SDLi_View będzie rozszerzać kilka może kilkanaście klas.

p.s. Później sprawdzanie czy kontroler jest 'wywoływalny'
  1. <?php
  2. if($module->doTrigger())
  3.            {
  4. ?>
, mam zamiar też wprowadzić po uruchomieniu metody init kontrolera.
Celem umożliwienia kontrolerowi zatrzymania wywoływania siebie samego.

edit>
Oczywiście Morkai za przykład wykorzystania debug_backtrace() zasłużone pomógł.
Swoją drogą może macie jeszcze jakieś inne pomysły na implementację czwartego modyfikatora dostępu external? tongue.gif

Ten post edytował orglee 13.12.2008, 15:44:38
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 27.06.2025 - 11:04