GORAGOD.com

การสร้าง class ที่สามารถเรียกใช้งานได้ทั้งแบบ static และแบบ ปกติ

การสร้างคลาสที่สามารถเรียกใช้งานได้ทั้งสองแบบ คือ แบบปกติ มีการใช้คำสั่ง new เพื่อสร้าง instance ของ class และแบบ static ซึ่งจะไปทำการสร้าง instance ให้โดยอัตโนมัติ สามารถทำได้โดยการใช้ magic function ของ PHP
  • __callStatic ฟังก์ชั่นนี้จะถูกเรียกใช้เมื่อมีการเรียก class แบบ static และเป็นการเรียกไปยัง method หรือ function ที่ไม่มีอยู่จริง หรือ ไม่สามารถเข้าถึงได้เท่านั้น
  • __call ฟังก์ชั่นนี้จะถูกเรียกใช้เมื่อมีการเรียก method หรือ function ของ class ที่ไม่มีอยู่จริง หรือ ไม่สามารถเข้าถึงได้ ตามตัวอย่างนี้ foo() และ bar() เป็น private ซึ่งปกติจะไม่สามารถเรียกใช้จากภายนอกคลาสได้
<?php
class myClass
{

    /**
     * ฟังก์ชั่นนี้จะทำหน้าที่ในการเรียกไปยัง private method (หรือ function)
     *
     * @param string $method
     * @param array $parameters
     * @return Method
     */

    public function __call($method, $parameters)
    {
        echo __FUNCTION__.'<br>';
        return call_user_func_array(array($this, $method), $parameters);
    }

    /**
     * ฟังก์ชั่นเรียกใช้งาน class แบบ static
     * ฟังก์ชั่นนี้ทำหน้าที่ในการสร้าง instance ของ class 
     *
     * @param string $method
     * @param array $parameters
     * @return Method
     */

    public static function __callStatic($method, $parameters)
    {
        echo __FUNCTION__.'<br>';
        $instance = new static;
        return call_user_func_array(array($instance, $method), $parameters);
    }

    /**
     * Class constructor
     *
     * @param array $param
     */

    public function __construct($param = null)
    {
        echo __FUNCTION__.'<br>';
    }

    /**
     * class method
     */

    private function foo()
    {
        echo __FUNCTION__.'<br>';
    }

    /**
     * class function
     */

    private function bar()
    {
        return __FUNCTION__;
    }
}

ตัวอย่างการเรียกใช้ Class
<?php
myClass::foo();
echo '--------------------------------<br>';
$ret = new myClass();
$ret->foo();
echo '--------------------------------<br>';
echo myClass::bar().'<br>';
echo '--------------------------------<br>';
$ret = new myClass();
echo $ret->bar().'<br>';
echo '--------------------------------<br>';

ลองสังเกตุผลลัพท์ดูนะครับว่ามีลำดับการเรียกใช้อย่างไร
__callStatic
__construct
foo
--------------------------------
__construct
__call
foo
--------------------------------
__callStatic
__construct
bar
--------------------------------
__construct
__call
bar
--------------------------------

ข้อเสียของวิธีนี้ก็มี
  • การเรียกใช้งานจะช้ากว่าแบบ public เล็กน้อย เนื่องจากมันต้องไปเรียกใช้งาน magic function ก่อน
  • Editor บางตัวอาจมองไม่เห็น method หรือ function เหล่านี้เนื่องจากมันเป็น private