Search code examples
phpstatictraits

PHP Trait static property


I have a class that extends Eloquent\Model. I want to define a trait that adds a static property and a static method to the class.

trait Searchable
{
  protected static array $searchable;

  public static function formatSearchQuery($value)
  {
    $queryArray = array();
    $paramArray = array();

    foreach (self::$searchable as $field) {
      $queryArray[] = "{$field} LIKE ?";
      $paramArray[] = $value . '%';
    }

    return ['query' => join(" OR ", $queryArray), 'params' => $paramArray];
  }
}

the aim is to define the fields that can be used in a text search query.

The problem I have is when I define my class like this:

class Benefit extends NAFModel
{
  use Searchable;
  /**
   * Name for table without prefix
   *
   * @var string
   */
  protected $table = 'naf_agenda_benefits';

  protected static array $searchable =
  [
    'name',
    'description',
  ];
}

I get the following error :

PHP Fatal error: NafAgenda\Eloquent\Client and NafAgenda\Traits\Searchable define the same property ($searchable) in the composition of NafAgenda\Eloquent\Client. However, the definition differs and is considered incompatible. Class was composed in /var/www/html/wp-content/plugins/naf-agenda-react/includes/Eloquent/Client.php on line 9


Solution

  • If a trait defines a property then a class can not define a property with the same name unless it is compatible (same visibility, type, readonly modifier and initial value), otherwise a fatal error is issued. (Reference from PHP Manual)

    Methods defined in traits can access methods and properties of the class, therefore we don't need to define searchable array in the Trait.

    <?php
    
    trait Searchable
    {
        public static function formatSearchQuery($value)
        {
            $queryArray = array();
            $paramArray = array();
    
            if (!is_array(self::$searchable ?? null)) {
              throw new Error(self::class . '::$searchable not iterable');
            }
    
            foreach (self::$searchable as $field) {
                $queryArray[] = "{$field} LIKE ?";
                $paramArray[] = $value . '%';
            }
    
            return ['query' => join(" OR ", $queryArray), 'params' => $paramArray];
        }
    
    }
    
    class Benefit extends NAFModel
    {
        use Searchable;
    
        protected static array $searchable = ['name', 'description'];
    
        /**
         * Name for table without prefix
         *
         * @var string
         */
        protected $table = 'naf_agenda_benefits';
    }
    
    print_r(Benefit::formatSearchQuery('Something'));