Bu bir PHP sınıfta alıcılar / ayarlayıcıları işlemek için makul bir yolu var mı?

8 Cevap php

Ben bu sorunun biçimi ile bir şey denemek için gidiyorum ve bunu işlemek için daha iyi bir yol hakkında önerileri çok açık değilim.

Ben refactormycode üzerinde sınıf için kod gönderdiniz yani sadece söz konusu kodun bir demet dökümü istemiyordu.

base class for easy class property handling

Benim düşünce insanlar geri refactorings için refactormycode değişiklikleri ve sonrası bağlantıları Posta kodu burada parçacıkları ya da yapabilirsiniz oldu. Ben buna dayanarak upvotes yapmak ve (açık bir "kazanan" var varsayarak) bir cevabı kabul edeceğiz.

Herhangi bir oranda, sınıfın kendisi için:

Ben alıcı / ayarlayıcı sınıf yöntemleri hakkında tartışma bir sürü görmek ve sadece doğrudan basit özellik değişkenleri erişmek için ya da her sınıf açık get / set yöntemleri tanımlanmış, falan filan olmalıdır iyidir. Ben daha sonra daha fazla mantığı eklemek için olması durumunda açık yöntemleri sahip fikir gibi. Sonra sınıfını kullanan herhangi bir kod değiştirmeniz gerekmez. Ancak bu gibi bakmak bir milyon fonksiyonları olan nefret:

public function getFirstName()
{
   return $this->firstName;
}
public function setFirstName($firstName)
{
   return $this->firstName;
}

Şimdi ben (Birisi bana önerebilirsiniz ki bunu yapmanın daha iyi bir yolu var olduğunu umuyorum) Bunu yapmak için ilk kişi değilim eminim.

Temelde, PropertyHandler sınıf bir __ çağrı sihirli yöntemi vardır. "Almak" veya "set" ile başlar __ çağrı yoluyla gelen herhangi yöntemleri sonra bir ilişkisel diziye değerlerini ayarlamak veya almak işlevlerine yönlendirilir. Diziye anahtar get veya set sonra arama yönteminin adıdır. __ Çağrı girdiği yöntemi "getFirstName" Yani, eğer, dizi anahtarı "Ad" dir.

Otomatik olarak alt sınıf zaten "getFirstName" yöntemi tanımlanmış olan davanın ilgilenir çünkü ben __ çağrısı kullanarak sevdim. Benim izlenimim (ve ben yanlış olabilir) olduğunu __ get & __set sihirli yöntemler bunu yapmaz.

Yani burada işe nasıl bir örnek:

class PropTest extends PropertyHandler
{
    public function __construct()
    {
        parent::__construct();
    }
}

$props = new PropTest();

$props->setFirstName("Mark");
echo $props->getFirstName();

PropTest aslında "setFirstName" veya "getFirstName" yöntemleri içermiyor ve PropertyHandler yapar ne dikkat edin. Yapıyor tüm dizi değerlerini manipüle olduğunu.

Alt sınıf zaten başka bir şey uzanan olduğu diğer durum olurdu. Eğer PHP gerçek çoklu mirası olamaz beri, sizin alt sınıf özel bir değişken olarak bir PropertyHandler örneği var yapabilirsiniz. Sen bir daha işlev eklemek zorunda ama sonra işler tam olarak aynı şekilde davranır.

class PropTest2
{
    private $props;

    public function __construct()
    {
        $this->props = new PropertyHandler();
    }

    public function __call($method, $arguments)
    {
        return $this->props->__call($method, $arguments);
    }
}

$props2 = new PropTest2();

$props2->setFirstName('Mark');
echo $props2->getFirstName();

Alt sınıf sadece PropertyHandler __ çağrı yöntemine boyunca her şeyi geçer bir __ çağrı yöntemi vardır nasıl fark.


Taşıma alıcılar ve ayarlayıcıları karşı başka iyi bir argüman bu yolu belgelemek için gerçekten zor hale olmasıdır.

Aslında, bu belgelendi yok edilecek açık yöntemler yoktur beri belge üretme aracı her türlü kullanabilirsiniz temelde imkansız.

Ben hemen hemen şimdi bu yaklaşımı terk ettik. Bu ilginç bir öğrenme bir egzersiz oldu ama ben çok fazla netlik feda düşünüyorum.

8 Cevap

Bunu yolu şudur:

class test {
    protected $x='';
    protected $y='';

    function set_y ($y) {
        print "specific function set_y\n";
        $this->y = $y;
    }

    function __call($function , $args) {
        print "generic function $function\n";
        list ($name , $var ) = split ('_' , $function );
        if ($name == 'get' && isset($this->$var)) {
            return $this->$var;
        }
        if ($name == 'set' && isset($this->$var)) {
            $this->$var= $args[0];
            return;
        }
        trigger_error ("Fatal error: Call to undefined method test::$function()");
    }
}

$p = new test();
$p->set_x(20);
$p->set_y(30);
print $p->get_x();
print $p->get_y();

$p->set_z(40);

Hangi çıktısı (hat sonları netlik eklenmiş)

generic function set_x
specific function set_y

generic function get_x
20
generic function get_y
30

generic function set_z
Notice: Fatal error: Call to undefined method set_z() in [...] on line 16

@Brian

Bu benim sorun ekleyerek "daha fazla mantık, daha sonra" Eğer alıcı / ayarlayıcı ile erişilen tüm özelliklerine geçerlidir battaniye mantığı eklemek ya da size uygulayabilirsiniz böylece erişiyor hangi özelliği değerlendirmek için ifadeler kullanmayın veya geçiş gerektirmesidir Belirli bir mantık.

Bu çok doğru değil. Benim ilk örneği ele alalım:

class PropTest extends PropertyHandler
{
    public function __construct()
    {
        parent::__construct();
    }
}

$props = new PropTest();

$props->setFirstName("Mark");
echo $props->getFirstName();

Diyelim ki FirstNames doğrulamak için bazı mantık eklemek gerekiyor diyelim. Yapmam gereken tek şey benim altsınıfına setFirstName yöntem eklemek ve bu yöntem yerine otomatik olarak kullanılır.

class PropTest extends PropertyHandler
{
    public function __construct()
    {
        parent::__construct();
    }

    public function setFirstName($name)
    {
        if($name == 'Mark')
        {
            echo "I love you, Mark!";
        }
    }
}

Ben sadece örtülü erişimcisine yöntemleri söz konusu olduğunda PHP olduğu sınırlamalar memnun değilim.

Ben tamamen katılıyorum. Ben bu işleme Python yolu (benim uygulaması bunun sadece beceriksiz bir soygun) gibi.

Evet bu doğru değişkenler elle beyan edilmesi gerekmektedir oluyor ama bulmak daha iyi ben setter bir yazım hatası korku beri

$props2->setFristName('Mark');

sert ayıklama yapacak yeni bir özellik (yerine FirstName FristName) otomatik üretecektir.

Bunun yerine sadece de, kamu alanları kullanma yöntemleri sahip Seviyorum ama PHP'nin varsayılan uygulama ile benim sorunum ((__ get kullanarak) ve __ set ()) veya özel uygulama, bir başına mülkiyet alıcı ve ayarlayıcıları kuran olmaması temelidir. Bu benim sorun ekleyerek "daha fazla mantık, daha sonra" Eğer alıcı / ayarlayıcı ile erişilen tüm özelliklerine geçerlidir battaniye mantığı eklemek ya da size uygulayabilirsiniz böylece erişiyor hangi özelliği değerlendirmek için ifadeler kullanmayın veya geçiş gerektirmesidir Belirli bir mantık.

Ben çözüm istiyorum, ben bunun için size alkışlıyorum - Ben sadece örtülü erişimcisine yöntemleri söz konusu olduğunda PHP olduğu sınırlamalar ile memnun değil.

@ Mark

Ancak bu bile senin yöntem yöntemin taze bir deklarasyon gerektirir ve daha fazla mantığı eklemek için çünkü biraz zaten, yöntemin eski moda deklarasyon gerektirir, daha fazla mantık ekleyebilir böylece yönteminde koyarak avantajı uzağa götürür. Varsayılan durumuna (o / does algılar ne etkileyici nerede olduğu) olarak, teknik kamu alanları üzerinde (PHP) hiçbir avantaj sunuyor. Sen alana erişimini kısıtlayan ancak kendi herhangi bir kısıtlama yok accessor yöntemlerle yetki veriyoruz. Ben kontrolsüz açık erişiciler any dilde kamu alanları üzerinde herhangi bir avantaj sunuyor farkında değilim, ama insanlar ve Yanılıyorsam beni düzeltin çekinmeyin gerekir yapabilirsiniz.

Ben her zaman benim sınıfların birçok Kazan plaka kodu olarak hemen hemen biter __ çağrısı ile benzer bu sorunu ele ettik. Ancak, kompakt ve sadece (yenilerini eklemek değil) zaten ayarlanmış olan özellikleri için alıcılar / ayarlayıcıları eklemek için yansıma sınıfları kullanır. Sadece açıkça alıcı / ayarlayıcı ekleyerek daha karmaşık işlevsellik katacak. Bu olmasını bekliyor

Kod bu gibi görünüyor:

/**
* Handles default set and get calls
*/
public function __call($method, $params) {

	//did you call get or set
	if ( preg_match( "|^[gs]et([A-Z][\w]+)|", $method, $matches ) ) {

		//which var?
		$var = strtolower($matches[1]);

		$r = new ReflectionClass($this);
		$properties = $r->getdefaultProperties();

		//if it exists
		if ( array_key_exists($var,$properties) ) {
			//set
			if ( 's' == $method[0] ) {
				$this->$var = $params[0];
			}
			//get
			elseif ( 'g' == $method[0] ) {
				return $this->$var;
			}
		}
	}
}

Eğer varsayılan özellikleri gibi ilan ettiler bir sınıf için bu ekleme:

class MyClass {
    public $myvar = null;
}

$test = new MyClass;
$test->setMyvar = "arapaho";

echo $test->getMyvar; //echos arapaho

Yansıma sınıfı öneren ne kadar kullanım şey ekleyebilirsiniz. Mark @ temiz çözüm.

Sadece son zamanlarda, ben de alıcılar işleme düşündüm ve önerilen şekilde (ikinci yaklaşım, benim en sevdiğim oldu Özel $ sahne dizinin yani) belirleyiciler, ama benim app çalıştım olmazdı için bunu atılır.

Ben oldukça büyük bir SoapServer tabanlı bir uygulama üzerinde çalışıyorum ve PHP 5 sabun arayüz sınıfta mevcut olan veya mevcut olmayan özellikleri düşünmeden, doğrudan ilişkili sınıfa sabun vasıtasıyla iletilir değerleri enjekte.

Benim 2 sent koyarak yardımcı olamaz ...

I http://gist.github.com/351387 (doktrin yapar benzer şekilde), daha sonra sadece hiç {yoluyla özelliklerine erişirken bu malikâne __get ve __set kullanarak almış [(3)]} sınıfın bir dış bölgesindeki. Yerine büyük bir __get veya __set function veya geçersiz kılma __get ve __set çocuğu yapma gerektiği gibi işlevini geçersiz Bu şekilde sınıflar.