PHP isset ($ this) ve statik ve nesne bağlamında aynı nesne yöntemi kullanarak

3 Cevap php

Ben çağıran statik fonksiyonu üzerinden erişilebilir yanı sıra nesne yöntemleri gereken bir sınıf üzerinde çalışıyorum. Ben buldum tek şey çoklu fonksiyonları üzerinde mantık çoğaltarak olmam.

Basitleştirilmiş bir örnek:

class Configurable{

    protected $configurations = array();

    protected static $static_configurations = array();

    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;

        }

    }

Ben buna bir çözüm bulduk, ama gerçekten kirli hissediyor:

class Configurable{

    protected $configurations = array();

    protected static $static_configurations = array();

    public function configure($name, $value){

        // ...lots of validation logic...

        if (isset($this)){
            $this->configurations[$name] = $value;
            }
        else{
            self::$static_configurations[$name] = $value;
            }

        }

    }

Ben uygulama boyunca yapılandırmaları ayarlayabilirsiniz böylece ben de statik işlev gerekir. Ayrıca, bu teknik ile güzel bir şey ben de kapsamları aynı yöntem adları kullanabilirsiniz olmasıdır.

Böyle test kapsamı ile herhangi bir sorun var mı? Performans sorunları, ileriye dönük uyumluluk sorunları, vb tüm PHP 5.2 benim için çalışır, ve ben <5 desteklemek gerekmez.

3 Cevap

Ikinci yöntem ile sorun hata raporlama E_STRICT olarak ayarlandığında bir hata neden olacaktır. Örneğin:

Sıkı standartları: Non-statik metot Foo :: bar () hat 10 üzerinde statik in / home / yacoby / dev / php / test.php denilen olmamalıdır

PHP6 ile bir nokta E_STRICT hataları E_ALL taşınır olmasıdır. Diğer bir deyişle E_ALL statik olmayan statik yöntemi çağırmak için izin vermiyor dahil tüm hataları kapsayacaktır.

Alternatif bir yöntem, statik bir işlev için doğrulama mantığını taşımak olabilir. Bu şekilde olmayan statik fonksiyonu ve statik işlev doğrulama mantığını arayabilirsiniz.

Ek argüman bir yürütme içeriği olacak - Statik yöntemler nesnel meslektaşı daha argümanlar farklı bir sayı gerektirir. Hiçbir yürütme içeriği varsa, o zaman only statik onu aramak için mantıklı.

Ben bu gibi çoklu arayüzler ile bir kütüphane inşa ediyorum ki verilen benim tercih edilen yaklaşım, bir statik sınıf ve dinamik bir sınıf oluşturmak için. Bir proxy diğer çağrıları var. Örneğin:

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) { ... }
}

Bu statik sınıfına içeriğini geçirmek tam olarak nasıl size kalmış - sizin için mantıklı ne yapmak gerekecek. (O zaman muhtemelen bir kural olarak küçük fonksiyonlara işi kesiliyor gerektiğini, bir çok yapıyoruz), ve bu yüzden sadece bağlam argümanlar bir avuç gerektiğini, en fonksiyonları yapılan çalışmalar oldukça küçük olmalıdır. Yoksa tam bağlam dizi oluşturmak ve ya başka her çağrı, ya da böylece hızlı ve o dizideki tüm DynamicClass özelliklerini izlemek önce sadece DynamicClass bunu doldurmamak (her yerde etrafında geçebileceği ; kolayca etrafında geçmektedir.


Eğer bir Singleton tasarım deseni yarar olabilir gibi aslında görünüyor olsa. Görebildiğim kadarıyla, küresel bir Configurable oluşturmak için çalışıyoruz, ve aynı zamanda bireysel yerel Configurable s oluşturmak için seçeneğiniz vardır ediyoruz. Singleton tasarım deseni sayesinde, size sadece (NYP tasarım ilkeleri kırma ve $ _GLOBALS vb güvenmek zorunda kalmadan) birine sahip garanti bir sınıfın dünya çapında erişilebilir sürümünü oluşturmak. Örneğin:

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;
    }
}

Olursa olsun kod nerede, sen DynamicClass::getSingleton() ile aynı örneği erişebilirsiniz. Ayrıca, bir-off tek sigara sürümlerini oluşturma seçeneği var. Sadece sadece akılda dinamik erişim ile tüm yöntemleri yazmak zorunda yaparken aslında her iki dünyanın en iyi olsun.

Ben de statik örneğinde bir yöntemi çağıran ve izin o kadar saçma bulmuyorum. Benim durum:

   TestRecord::generateForm(); // Generate an empty form.

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

Static side of my class deals with blank/new logics, while instance side means live data are used.

PHP 5.3 __call, __callStatic ve static:: kullanarak bunu başarmak için izin verir:

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.
  }
}

Note, static:: geç bağlama eleme kullanılır, çünkü benim 3 hareket şekli (createFields, fillFields ve rendreForm ) 'dir, bu birine ait alt sınıfları içinde protected şeklinde uygulanan abstract. Tabanından alt sınıf, ama alt sınıfın yanı SuperClass için: PHP korumalı üyeleri her iki yönde de ulaşılabilir edelim, çünkü bu mümkün. Bildiğim kadarıyla, diğer OO dillerde farklı olduğu.