SmartObject ve StaticClass
SmartObject PHP sınıflarına property desteği ekler. StaticClass statik sınıfları belirtmek için kullanılır.
Kurulum:
composer require nette/utils
Özellikler, Getiriciler ve Ayarlayıcılar
Modern nesne yönelimli dillerde (örneğin C#, Python, Ruby, JavaScript) property terimi, sınıfların değişken gibi görünen ancak aslında yöntemlerle temsil edilen özel üyelerini ifade eder. Bu “değişkenin” değeri atandığında veya okunduğunda, ilgili yöntem (getter veya setter olarak adlandırılır) çağrılır. Bu çok kullanışlı bir şeydir, bize değişkenlere erişim üzerinde tam kontrol sağlar. Girdiyi doğrulayabilir veya yalnızca özellik okunduğunda sonuç üretebiliriz.
PHP özellikleri desteklenmez, ancak trait Nette\SmartObject
bunları taklit edebilir. Nasıl kullanılır?
- Sınıfa şu biçimde bir ek açıklama ekleyin
@property <type> $xyz
getXyz()
veyaisXyz()
adında bir getter, adında bir setter oluşturun.setXyz()
- Getter ve setter public veya protected olmalıdır ve isteğe bağlıdır, bu nedenle read-only veya write-only özelliği olabilir
$radius
değişkenine yalnızca negatif olmayan sayıların girilmesini sağlamak için Circle sınıfının
özelliğini kullanacağız. public $radius
öğesini özellik ile değiştirin:
/**
* @property float $radius
* @property-read bool $visible
*/
class Circle
{
use Nette\SmartObject;
private float $radius = 0.0; // herkese açık değil
//radius özelliği için getter
protected function getRadius(): float
{
return $this->radius;
}
//radius özelliği için setter
protected function setRadius(float $radius): void
{
// kaydetmeden önce değeri sanitize etme
$this->radius = max(0.0, $radius);
}
// özellik için getter $visible
protected function isVisible(): bool
{
return $this->radius > 0;
}
}
$circle = new Circle;
$circle->radius = 10; // aslında setRadius(10) çağırır
echo $circle->radius; // getRadius() işlevini çağırır
echo $circle->visible; // isVisible() işlevini çağırır
Özellikler öncelikle sözdizimsel şeker olup, kodu basitleştirerek programcının hayatını daha tatlı hale getirmeyi amaçlar. Eğer onları istemiyorsanız, kullanmak zorunda değilsiniz.
Statik Sınıflar
Statik sınıflar, yani örneklenmesi amaçlanmayan sınıflar, Nette\StaticClass
özelliği ile
işaretlenebilir:
class Strings
{
use Nette\StaticClass;
}
Bir örnek oluşturmaya çalıştığınızda, sınıfın statik olduğunu belirten Error
istisnası atılır.
Tarihe Bir Bakış
SmartObject eskiden sınıf davranışını birçok yönden geliştirir ve düzeltirdi, ancak PHP'nin evrimi orijinal özelliklerin çoğunu gereksiz hale getirdi. Bu nedenle aşağıda, işlerin nasıl geliştiğinin geçmişine bir bakış yer almaktadır.
PHP nesne modeli en başından beri bir dizi ciddi kusur ve verimsizlikten muzdaripti. Bu eksiklikleri gidermeye ve PHP
kullanım deneyimini iyileştirmeye çalışan Nette\Object
sınıfının (2007'de) yaratılmasının nedeni buydu.
Diğer sınıfların bu sınıftan miras alması ve sağladığı avantajlardan yararlanması için yeterliydi. PHP 5.4 trait
desteği ile geldiğinde, Nette\Object
sınıfı Nette\SmartObject
ile değiştirildi. Böylece artık
ortak bir atadan miras almaya gerek kalmamıştı. Ayrıca, trait zaten başka bir sınıftan miras alan sınıflarda da
kullanılabiliyordu. Nette\Object
'un nihai sonu, sınıfların Object
olarak adlandırılmasını
yasaklayan PHP 7.2 sürümüyle geldi.
PHP'nin gelişimi devam ettikçe, nesne modeli ve dil yetenekleri geliştirildi. SmartObject
sınıfının
bireysel işlevleri gereksiz hale geldi. PHP 8.2'nin yayınlanmasından bu yana, PHP'de henüz doğrudan desteklenmeyen tek
özellik, sözde özellikleri kullanma yeteneğidir.
Nette\Object
ve Nette\Object
bir zamanlar hangi özellikleri sunuyordu? İşte genel bir bakış.
(Örnekler Nette\Object
sınıfını kullanmaktadır, ancak özelliklerin çoğu Nette\SmartObject
özelliği için de geçerlidir).
Tutarsız Hatalar
PHP, bildirilmemiş üyelere erişirken tutarsız davranışlar sergiliyordu. Nette\Object
adresinin durumu
aşağıdaki gibiydi:
echo $obj->undeclared; // E_NOTICE, daha sonra E_WARNING
$obj->undeclared = 1; // raporlama yapmadan sessizce geçer
$obj->unknownMethod(); // Ölümcül hata (try/catch ile yakalanamaz)
Ölümcül hata, herhangi bir tepki verme imkanı olmadan uygulamayı sonlandırdı. Var olmayan üyelere uyarı vermeden
sessizce yazmak, tespit edilmesi zor ciddi hatalara yol açabilirdi. Nette\Object
Tüm bu durumlar yakalandı ve bir
istisna MemberAccessException
atıldı.
echo $obj->undeclared; // throw Nette\MemberAccessException
$obj->undeclared = 1; // throw Nette\MemberAccessException
$obj->unknownMethod(); // throw Nette\MemberAccessException
PHP 7.0'dan beri PHP artık yakalanamayan ölümcül hatalara neden olmamaktadır ve bildirilmemiş üyelere erişim PHP 8.2'den beri bir hatadır.
Ne demek istiyorsun?
Bir nesne değişkenine erişirken veya bir yöntemi çağırırken yapılan yazım hatası nedeniyle
Nette\MemberAccessException
hatası atıldığında, Nette\Object
hata mesajında hatanın nasıl
düzeltileceğine dair ikonik “demek istediniz mi?” eki şeklinde bir ipucu vermeye çalışmıştır.
class Foo extends Nette\Object
{
public static function from($var)
{
}
}
$foo = Foo::form($var);
// throw Nette\MemberAccessException
// "Call to undefined static method Foo::form(), did you mean from()?"
Günümüz PHP'sinde “demek istediniz mi?” gibi bir ifade bulunmayabilir, ancak Tracy hatalara bu eki ekler. Ve bu tür hataları kendisi bile düzeltebilir.
Uzatma yöntemleri
C#'ın uzantı yöntemlerinden esinlenilmiştir. Mevcut sınıflara yeni yöntemler ekleme imkanı verdiler. Örneğin, kendi
DateTimePicker'ınızı eklemek için bir forma addDateTime()
yöntemini ekleyebilirsiniz.
Form::extensionMethod(
'addDateTime',
fn(Form $form, string $name) => $form[$name] = new DateTimePicker,
);
$form = new Form;
$form->addDateTime('date');
Uzatma yöntemlerinin pratik olmadığı kanıtlandı çünkü isimleri editörler tarafından otomatik olarak tamamlanmadı, bunun yerine yöntemin mevcut olmadığını bildirdiler. Bu nedenle destekleri kesilmiştir.
Sınıf Adını Alma
$class = $obj->getClass(); // using Nette\Object
$class = $obj::class; // PHP 8.0'dan beri
Yansıma ve Ek Açıklamalara Erişim
Nette\Object
getReflection()
ve getAnnotation()
yöntemlerini kullanarak yansıtma ve ek
açıklamaya erişim sundu:
/**
* @author John Doe
*/
class Foo extends Nette\Object
{
}
$obj = new Foo;
$reflection = $obj->getReflection();
$reflection->getAnnotation('author'); // 'John Doe' döndürür
PHP 8.0'dan itibaren meta-bilgilere öznitelikler şeklinde erişmek mümkündür:
#[Author('John Doe')]
class Foo
{
}
$obj = new Foo;
$reflection = new ReflectionObject($obj);
$reflection->getAttributes(Author::class)[0];
Yöntem Getiriciler
Nette\Object
metotları değişkenlermiş gibi ele almak için zarif bir yol sundu:
class Foo extends Nette\Object
{
public function adder($a, $b)
{
return $a + $b;
}
}
$obj = new Foo;
$method = $obj->adder;
echo $method(2, 3); // 5
PHP 8.1'den itibaren, birinci sınıf çağrılabilir sözdizimi olarak adlandırılan sözdizimini:https://www.php.net/…lable_syntax kullanabilirsiniz:
$obj = new Foo;
$method = $obj->adder(...);
echo $method(2, 3); // 5
Etkinlikler
Nette\Object
olayı tetiklemek için sözdizimsel
şeker sundu:
class Circle extends Nette\Object
{
public array $onChange = [];
public function setRadius(float $radius): void
{
$this->onChange($this, $radius);
$this->radius = $radius
}
}
$this->onChange($this, $radius)
kodu aşağıdakine eşdeğerdir:
foreach ($this->onChange as $callback) {
$callback($this, $radius);
}
Netlik açısından sihirli yöntemden kaçınmanızı öneririz $this->onChange()
. Pratik bir ikame Nette\Utils\Arrays::invoke fonksiyonudur:
Nette\Utils\Arrays::invoke($this->onChange, $this, $radius);