Question:
I'm implementing a filter functionality in some classes of my application through traits
.
The trait
function will resort to class variables through some properties defined in the class:
<?php
trait FilterTrait {
public function scopeApplyFilters($filters) {
foreach (self::$allowedFilters as $filter) {
// Executa método
}
}
}
class EstoqueMeta extends Eloquent {
use FilterTrait;
static public $allowedFilters = array('foo','bar');
}
I would like to force from the trait
that the property be defined in the class. I thought to implement this functionality from inheritance, but I would lose the flexibility of using the trait
in other parts of my application.
Is there any way to "force" the declaration of properties from the trait
? If not, are there any alternatives without involving inheritance?
My problem is not declaring the property on trait
, this was my first attempt, but if the class has the same property, there will be a collision error with the name of the properties.
trait FilterTrait {
public $allowedFilters = array();
public function scopeApplyFilters($filters) {
foreach (self::$allowedFilters as $filter) {
// Executa método
}
}
}
class EstoqueMeta {
use FilterTrait;
public $allowedFilters = array('foo', 'bar');
}
Fatal error: EstoqueMeta and FilterTrait defines the same property ($allowedFilters) in the composition of EstoqueMeta. However, the definition differs and is considered incompatible. Class was composed in […][…] on line 23
Answer:
I believe it is not possible to do what you want, properties are at best inherited as far as I know. But it's possible to solve this without needing to set a property, you can leave a method for your class to implement, you can use an interface or leave an abstract method on your trait to do that
Example:
trait FilterTrait
{
abstract public function getAllowedFilters();
public function scopeApplyFilters(array $filters)
{
foreach ($filters as $filter) {
if (false === \in_array($filter, $this->getAllowedFilters())) {
}
}
}
}
class EstoqueMeta
{
use FilterTrait;
public function getAllowedFilters()
{
return array('foo', 'bar');
}
}
$estoque = new EstoqueMeta();
$estoque->scopeApplyFilters(array('foo'));