PHP isset ($ this) e utilizzo dello stesso metodo object in un context statico e object

Sto lavorando su una class che deve essere accessibile tramite chiamate a funzioni statiche e methods object. Una cosa che ho trovato è che sto duplicando la logica tra più funzioni.

Esempio semplificato:

class Configurable{ protected $configurations = arrays(); protected static $static_configurations = arrays(); public function configure($name, $value){ // ...lots of validation logic... $this->configurations[$name] = $value; } public static function static_configure($name, $value){ // ...lots of validation logic (repeated)... self::$static_configurations[$name] = $value; } } 

Ho trovato una soluzione a questo, ma sembra davvero sporco:

 class Configurable{ protected $configurations = arrays(); protected static $static_configurations = arrays(); public function configure($name, $value){ // ...lots of validation logic... if (isset($this)){ $this->configurations[$name] = $value; } else{ self::$static_configurations[$name] = $value; } } } 

Ho bisogno anche della function statica per poter configurare le configurazioni in tutta l'applicazione. Inoltre, la cosa bella con questa tecnica è che posso usare gli stessi nomi di metodo in entrambi gli ambiti.

Ci sono problemi con l'ambito del test in questo modo? Problemi di performance, problemi di compatibilità diretta, ecc. Funziona tutto per me su PHP 5.2, e non ho bisogno di supportre <5.

Il problema con il secondo metodo è che causerà un errore quando la segnalazione degli errori è impostata su E_STRICT . Per esempio:

Standard rigorosi: metodo non statico Foo :: bar () non dovrebbe essere chiamato staticamente in /home/yacoby/dev/php/test.php sulla row 10

Un punto con PHP6 è che gli errori E_STRICT vengono spostati su E_ALL. In altre parole, E_ALL coprirà tutti gli errori, incluso il non consentire all'utente di call staticamente methods non statici.

Un metodo alternativo può essere quello di spostare la logica di validation in una function statica. In questo modo la function non statica e la function statica possono call la logica di validazione.

I methods statici richiederebbero un numero diverso di argomenti rispetto alla loro controparte oggettiva – l'argomento addizionale sarebbe un context di esecuzione. Se non c'è un context di esecuzione, allora ha senso solo chiamarlo staticamente.

Il mio approccio preferito dato che sto costruendo una libreria con più interfacce come questa, è quello di creare una class statica e una class dynamic. Avere un proxy le chiamate all'altro. Per esempio:

 class DynamicClass { protected $foo; protected $bar; public function baz($arg1) { return StaticClass::bar($this->foo, $arg1); } public function zop($arg1, $arg2) { return StaticClass::zop($this->foo, $this->bar, $arg1, $arg2); } // Context-less helper function public function womp($arg1) { return StaticClass::womp($arg1); } } class StaticClass { public static function baz(&$fooContext, $arg1) { ... } public static function zop(&$fooContext, &$barContext, $arg1, $arg2) { ... } public static function womp($arg1) { ... } } 

Spetta a te esattamente come passare il context alla class statica: dovrai fare tutto ciò che ha senso per te. Il lavoro svolto nella maggior parte delle funzioni dovrebbe essere piuttosto limitato (se si sta facendo molto, allora probabilmente si dovrebbe interrompere il lavoro in funzioni più piccole di solito), e quindi dovrebbe solo richiedere una manciata di argomenti di context. Oppure puoi creare una matrix di context completa e passarla dappertutto ( DynamicClass in DynamicClass appena prima di each chiamata, oppure tracciare tutte le properties; di DynamicClass in quell'arrays in modo che tu possa passarla rapidamente e facilmente.


Anche se in realtà sembra che tu possa beneficiare di un model di design Singleton. Da quello che vedo, stai cercando di creare un Configurable globale e hai anche la possibilità di creare singoli Configurable locali. Con il model di progettazione singleton, crei una versione accessibile a livello globale di una class che puoi garantire di avere solo una (senza violare i principi di progettazione OOP e wherer fare affidamento su $ _GLOBALS, ecc.). Per esempio:

 class DynamicClass { protected $foo; protected $bar; public function baz($arg1) { ... } public function zop($arg1, $arg2) { ... } public static function getSingleton() { static $instance = null; if ($instance === null) $instance = new DynamicClass(); return $instance; } } 

Indipendentemente da where ti trovi nel tuo codice, puoi accedere alla stessa istanza con DynamicClass::getSingleton() . Hai anche la possibilità di creare versioni one-off non-singleton. In pratica ottieni il meglio da entrambi i mondi mentre devi solo scrivere tutti i tuoi methods con un accesso dinamico in mente esclusivamente.

Non trovo così assurdo permettere di call un metodo su un'istanza e anche staticamente. Il mio caso:

  TestRecord::generateForm(); // Generate an empty form. $test = new TestRecord( $primaryKey ); [...] $test->generateForm(); // Generate an edit form with actual $test values. 

Il lato statico della mia class si occupa di logiche vuote / nuove, mentre lato istanza significa che i dati in tempo reale vengono utilizzati.

PHP 5.3 consente di get ciò usando __call , __callStatic e static:: __callStatic

 public function __call( $name, $args ) { if ( $name == 'generateForm' ) { $this->fields = static::createFields(); // Action 1 : static. $this->fillFields(); // Action 2 : instance. static::renderForm( $this->fields ); // Action 3 : static. } } public static function __callStatic( $name, $args ) { if ( $name == 'generateForm' ) { $fields = static::createFields(); // Action 1 : static. // Action 2 : none. static::renderForm( $fields ); // Action 3 : static. } } 

Nota : il qualificatore di static:: late binding viene utilizzato perché i miei 3 methods di azione ( createFields , fillFields e rendreForm ) sono implementati come protected nelle sottoclassi di questo, che è abstract . Questo è ansible perché PHP consente l'accesso ai membri protetti in entrambe le direzioni: dalla base alla sottoclass, ma anche dalla sottoclass alla superclass. Che è diverso dalle altre lingue OO, per quanto ne so.

come nel core php usiamo index.php?var= , così per fare la stessa cosa in oop php cosa dovremmo usare.