Avoiding boilerplate in PHP classes

I am working on a PHP code and as it grows getting more and more tired of repeating the same standard pattern again and again and again:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class BolerPlate
{
protected $property1;
protected $property2;
...
public function __construct ($property1, $property2, ...)
{
$this->property1 = $property1;
$this->property2 = $property2;
...
}
}
</code>
<code>class BolerPlate { protected $property1; protected $property2; ... public function __construct ($property1, $property2, ...) { $this->property1 = $property1; $this->property2 = $property2; ... } } </code>
class BolerPlate
{
    protected $property1;
    protected $property2;
    ...

    public function __construct ($property1, $property2, ...)
    {
        $this->property1 = $property1;
        $this->property2 = $property2;
        ...
    }
}

So I am re-typing here each property name 4 (!) times just to get the standard setup! In each class! It doesn’t look elegant nor DRY to me. And re-typing the same names creates more bug opportunities.

I wonder if there is any more elegant way or best practices to get the same setup with a code easier on the eyes 🙂

EDIT. What I have in mind is some sort of factory method where I can supply the list of properties only once each. Or using variable variables and iterate over all properties?

8

In short: Traits might be the feature that you look for.

A trait is PHP 5.4’s solution to the lack of multiple inheritance in the language and a way to avoid hierarchical inheritance chains. Another way to think of it is that including traits in your classes is a clean way to keep your code dry without breaking good design principles.

An even more simple way to think about it is: Hey, all that boiler plate code that you copied and pasted everywhere but now you want to change something? well replace it with a trait and call it a day.

Here you are examples and good post on this topic.

4

Here is some possible solution to my question inspired by this answer. In its laziest form it looks so:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public function __construct ($propertyArray) {
foreach ($propertyArray as $property) {
$this->$property = $property;
}
}
</code>
<code>public function __construct ($propertyArray) { foreach ($propertyArray as $property) { $this->$property = $property; } } </code>
public function __construct ($propertyArray) {
    foreach ($propertyArray as $property) {
        $this->$property = $property;
    }
}

So you pass all arguments as array and then the code becomes uniform and can be inherited from. You still have to write the list of protected variables manually since the following (sadly) doesn’t work:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> foreach ($propertyArray as $property) {
protected $property; // or private $this->property
}
</code>
<code> foreach ($propertyArray as $property) { protected $property; // or private $this->property } </code>
    foreach ($propertyArray as $property) {
        protected $property; // or private $this->property
    }

and there seem to be no easy way around :(.
The real problem here, far worse then just few extra lines to type, is the consequence of misprints, that can lead to creation of wrong private properties, whereas correct properties from the array become public against dev’s intention.

The same problem actually affects the original traditional way just as much.

A partial solution is to use the trick inspired by the mentioned answer:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public function __construct ($propertyArray) {
foreach ($propertyArray as $property) {
$prefixedProperty = 'prefix' . ucfirst(strtolower($property));
$this->$prefixedProperty = $property;
}
}
</code>
<code>public function __construct ($propertyArray) { foreach ($propertyArray as $property) { $prefixedProperty = 'prefix' . ucfirst(strtolower($property)); $this->$prefixedProperty = $property; } } </code>
public function __construct ($propertyArray) {
    foreach ($propertyArray as $property) {
        $prefixedProperty = 'prefix' . ucfirst(strtolower($property));
        $this->$prefixedProperty = $property;
    }
}

So you hide the property by adding 'prefix' to its name, so-called security by obscurity :). Now the property is still public in case of misprint but you hope not to hit it so easily. Still not 100% bullet-proof.

Now here is the best solution I came up with:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class BulletProof {
protected $myProperty = '';
public function __construct ($propertyArray) {
foreach ($propertyArray as $property) {
if (! isset($this->$property) ) {
throw new exception("Careful, buddy! You either forgot or mistyped your declaration of $property!";
}
$this->$property = $property;
}
}
}
</code>
<code>class BulletProof { protected $myProperty = ''; public function __construct ($propertyArray) { foreach ($propertyArray as $property) { if (! isset($this->$property) ) { throw new exception("Careful, buddy! You either forgot or mistyped your declaration of $property!"; } $this->$property = $property; } } } </code>
class BulletProof {
    protected $myProperty = '';

    public function __construct ($propertyArray) {
        foreach ($propertyArray as $property) {
            if (! isset($this->$property) ) {
               throw new exception("Careful, buddy! You either forgot or mistyped your declaration of $property!";
            }
            $this->$property = $property;
        }
    }        
}

So if you mistyped or forgot to declare the variable, compiler warns you with exception! To make it work, you have to initialize all your variables with something different from null, which is not too much of a burden, since they got overwritten by the constructor.

If anyone knows a more elegant way, I’d be happy to learn.


On another note I am grateful to Yannis Rizos for his suggestions in private chat, which involve using magic methods __set and __get, still with the consequence that properties become public.

First off, I understand your pain. If you use namespaces, add a use statement and type hint for any class dependency bringing the total to six.

Variable variables or any other hackery may save you some bulk now, but it’s going to hurt you in the long run. Traits assume you are re-using code, which probably isn’t the case, or at least it won’t be every time.

The best thing you can do is minimize dependencies per class and try to keep things from getting out of hand. You can use macros, templates or whatever you want to call them to only type it once per dependency. This helps with keystrokes, but the resulting code will still be repetitive.

Sorry, this is the current state of PHP.

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Avoiding boilerplate in PHP classes

I am working on a PHP code and as it grows getting more and more tired of repeating the same standard pattern again and again and again:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class BolerPlate
{
protected $property1;
protected $property2;
...
public function __construct ($property1, $property2, ...)
{
$this->property1 = $property1;
$this->property2 = $property2;
...
}
}
</code>
<code>class BolerPlate { protected $property1; protected $property2; ... public function __construct ($property1, $property2, ...) { $this->property1 = $property1; $this->property2 = $property2; ... } } </code>
class BolerPlate
{
    protected $property1;
    protected $property2;
    ...

    public function __construct ($property1, $property2, ...)
    {
        $this->property1 = $property1;
        $this->property2 = $property2;
        ...
    }
}

So I am re-typing here each property name 4 (!) times just to get the standard setup! In each class! It doesn’t look elegant nor DRY to me. And re-typing the same names creates more bug opportunities.

I wonder if there is any more elegant way or best practices to get the same setup with a code easier on the eyes 🙂

EDIT. What I have in mind is some sort of factory method where I can supply the list of properties only once each. Or using variable variables and iterate over all properties?

8

In short: Traits might be the feature that you look for.

A trait is PHP 5.4’s solution to the lack of multiple inheritance in the language and a way to avoid hierarchical inheritance chains. Another way to think of it is that including traits in your classes is a clean way to keep your code dry without breaking good design principles.

An even more simple way to think about it is: Hey, all that boiler plate code that you copied and pasted everywhere but now you want to change something? well replace it with a trait and call it a day.

Here you are examples and good post on this topic.

4

Here is some possible solution to my question inspired by this answer. In its laziest form it looks so:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public function __construct ($propertyArray) {
foreach ($propertyArray as $property) {
$this->$property = $property;
}
}
</code>
<code>public function __construct ($propertyArray) { foreach ($propertyArray as $property) { $this->$property = $property; } } </code>
public function __construct ($propertyArray) {
    foreach ($propertyArray as $property) {
        $this->$property = $property;
    }
}

So you pass all arguments as array and then the code becomes uniform and can be inherited from. You still have to write the list of protected variables manually since the following (sadly) doesn’t work:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> foreach ($propertyArray as $property) {
protected $property; // or private $this->property
}
</code>
<code> foreach ($propertyArray as $property) { protected $property; // or private $this->property } </code>
    foreach ($propertyArray as $property) {
        protected $property; // or private $this->property
    }

and there seem to be no easy way around :(.
The real problem here, far worse then just few extra lines to type, is the consequence of misprints, that can lead to creation of wrong private properties, whereas correct properties from the array become public against dev’s intention.

The same problem actually affects the original traditional way just as much.

A partial solution is to use the trick inspired by the mentioned answer:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public function __construct ($propertyArray) {
foreach ($propertyArray as $property) {
$prefixedProperty = 'prefix' . ucfirst(strtolower($property));
$this->$prefixedProperty = $property;
}
}
</code>
<code>public function __construct ($propertyArray) { foreach ($propertyArray as $property) { $prefixedProperty = 'prefix' . ucfirst(strtolower($property)); $this->$prefixedProperty = $property; } } </code>
public function __construct ($propertyArray) {
    foreach ($propertyArray as $property) {
        $prefixedProperty = 'prefix' . ucfirst(strtolower($property));
        $this->$prefixedProperty = $property;
    }
}

So you hide the property by adding 'prefix' to its name, so-called security by obscurity :). Now the property is still public in case of misprint but you hope not to hit it so easily. Still not 100% bullet-proof.

Now here is the best solution I came up with:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class BulletProof {
protected $myProperty = '';
public function __construct ($propertyArray) {
foreach ($propertyArray as $property) {
if (! isset($this->$property) ) {
throw new exception("Careful, buddy! You either forgot or mistyped your declaration of $property!";
}
$this->$property = $property;
}
}
}
</code>
<code>class BulletProof { protected $myProperty = ''; public function __construct ($propertyArray) { foreach ($propertyArray as $property) { if (! isset($this->$property) ) { throw new exception("Careful, buddy! You either forgot or mistyped your declaration of $property!"; } $this->$property = $property; } } } </code>
class BulletProof {
    protected $myProperty = '';

    public function __construct ($propertyArray) {
        foreach ($propertyArray as $property) {
            if (! isset($this->$property) ) {
               throw new exception("Careful, buddy! You either forgot or mistyped your declaration of $property!";
            }
            $this->$property = $property;
        }
    }        
}

So if you mistyped or forgot to declare the variable, compiler warns you with exception! To make it work, you have to initialize all your variables with something different from null, which is not too much of a burden, since they got overwritten by the constructor.

If anyone knows a more elegant way, I’d be happy to learn.


On another note I am grateful to Yannis Rizos for his suggestions in private chat, which involve using magic methods __set and __get, still with the consequence that properties become public.

First off, I understand your pain. If you use namespaces, add a use statement and type hint for any class dependency bringing the total to six.

Variable variables or any other hackery may save you some bulk now, but it’s going to hurt you in the long run. Traits assume you are re-using code, which probably isn’t the case, or at least it won’t be every time.

The best thing you can do is minimize dependencies per class and try to keep things from getting out of hand. You can use macros, templates or whatever you want to call them to only type it once per dependency. This helps with keystrokes, but the resulting code will still be repetitive.

Sorry, this is the current state of PHP.

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật