Search code examples
phpyii2

How to get grid behavior columns dynamically?


I'm making a plugin system and I'm dynamically adding behaviors with relation to Order model. For example:

class OrderBehavior extends Behavior
{
    public function getOrderTrackNumber()
    {
        return $this->owner->hasOne(TrackNumber::class, ['order_id' => 'id']);
    }
}

At runtime I don't know which plugins (and therefore which behaviors) are activated.

How can I get all relation properties (in example orderTrackNumber) dynamically for render in GridView columns?


Solution

  • You may use getBehaviors() to get all active behaviors attached to model. At this point you should probably implement some interface for behaviors which may add new relations, so they will be able to provide list of defined relations - it may save you performance hell (browsing all behavior's methods and searching relations definitions may be slow and unreliable). For example:

    interface BehaviorWithRelationsInterface {
    
        /**
         * @return string[]
         */
        public function getRelationsNames(): array;
    }
    

    Then in model:

    /**
     * @return string[]
     */
    public function getAllRelationsNames(): array {
        $relations = [];
        foreach ($this->getBehaviors() as $behavior) {
            if ($behavior instanceof BehaviorWithRelationsInterface) {
                $relations = array_merge($relations, $behavior->getRelationsNames());
            }
        }
    
        // add relations defined directly in model
        $relations[] = 'user';
    
        return $relations;
    }
    

    If you don't miss anything, getAllRelationsNames() should return names of all relations defined in model.