Search code examples
phpcodeignitercodeigniter-4

Possible to group class functions and access them by group in PHP/Codeigniter?


I have a library in my CodeIgniter4 project, now I want to make my lib with lots of functions more clear.

For that I want to know if its possible to group the functions inside the class-definition by a kind of groups and make them accessible by the group-name.

What I mean: The function "my_classfunction" of the lib "mylib" I normally use by "$this->mylib->my_classfunction()"-

Now I think to make groups of functions and access them by a kind of group-name for example "function funcA is in group testA, funB is in group testB" and use it in a kind like "$this->mylib->testA->funcA()" - is something like this possible, and if, how?


Solution

  • What you need to do is create a class that will manage your groups. Register your mylib with the class ClassGroup, so when you call $this->mylib, it will return instance of ClassGroup. With the magic method and singleton method, you can now call based on group and even with shared singleton instance

    To ensure IDE friendly, use phpdoc annotation to declare classes and properties.

    Class Example:

    /**
     * Class Properties.
     *
     * @property TextClassA $testA Get instance of TextClassA.
     * @property TextClassB $testB Get instance of TextClassB.
     * 
     * Class Methods.
     * 
     * @method TextClassA testA(mixed ...$arguments) Return instance of TextClassA with new arguments.
     * @method TextClassA testB(mixed ...$arguments) Return instance of TextClassB with new arguments.
     */
    class ClassGroup 
    {
        private static array $instance = [];
        private bool $shared = false;
    
        public function __construct(bool $shared = false)
        {
            $this->shared = $shared;
        }
    
        public function __get(string $group): ?object 
        {
            return $this->shared 
                ? self::getInstance($group) 
                : self::groups($group);
        }
        
    
        public function __call(string $method, array $arguments): ?object 
        {
            return $this->shared 
                ? self::getInstance($method, $arguments) 
                : self::groups($method, $arguments);
        }
    
        public function singleton(): self 
        {
            $this->shared = true;
            return $this;
        }
    
        private static function getInstance(string $method, array $arguments): ?object 
        {
            if(!isset(self::$instance[$method])){
                self::$instance[$method] = self::groups($method, $arguments);
            }
    
            return self::$instance[$method];
        }
    
        private static function groups(string $group, array $arguments): ?object 
        {
            return match($group)
            {
                'testA' => new TextClassA(...$arguments),
                'testB' => new TextClassB(...$arguments),
                default => null
            };
        } 
    }
    

    Usages examples:

    $this->mylib->testA->fooMethod();
    $this->mylib->testA('foo', 'bar')->fooMethod();
    
    // For shared instance 
    
    $this->mylib->singleton()->testA->fooMethod();
    $this->mylib->singleton()->testA('foo', 'bar')->fooMethod();