2012-06-19 5 views
1

У меня есть базовый класс со многими подклассами и общая функция для кэширования результатов функции. В функции кеша, как я могу определить, какой подкласс был вызван?Как узнать, какой класс был вызван ранее?

class Base { 
    public static function getAll() { 
    return CacheService::cached(function() { 
     // get objects from the database 
    }); 
    } 
} 

class X extends Base {} 
class Y extends Base {} 
class Z extends Base {} 

class CacheService { 
    function cached($callback) { 
    list(, $caller) = debug_backtrace(); 

    // $caller['class'] is always Base! 
    // cannot use get_called_class as it returns CacheService! 

    // see if function is in cache, otherwise do callback and store results 
    } 
} 

X::getAll(); 
Z::getAll(); 

ответ

1

Если you'r используя PHP> = 5.3, вы можете сделать это с помощью get_called_class().

Edit: Чтобы сделать его более ясным, get_called_class() должен быть использован в методе Base::getAll(). Вы, конечно же, в таком случае придется сказать CacheService::cached() какой класс этом сообщил (добавление метода аргумент будет наиболее прямой способ):

class Base { 
    public static function getAll() { 
    return CacheService::cached(get_called_class(), function() { 
     // get objects from the database 
    }); 
    } 
} 

class X extends Base {} 
class Y extends Base {} 
class Z extends Base {} 

class CacheService { 
    function cached($caller, $callback) { 
    // $caller is now the child class of Base that was called 

    // see if function is in cache, otherwise do callback and store results 
    } 
} 

X::getAll(); 
Z::getAll(); 
+0

Ergo, это невозможно сделать, не передавая дополнительный параметр CacheService :: cached? – Aistina

+0

@Aistina: Нет, это невозможно. Но делать это таким образом - это наиболее удобный способ, не переделывая то, что вы делаете, так что вам не нужно делать то, что, по вашему мнению, вам нужно делать. Но если вы настроитесь на это так, вы можете переопределить 'Base :: getAll()' во всех своих дочерних классах и заставить их ничего не делать, кроме вызова 'parent :: getAll()', который будет помещать эти методы в стек, и затем вы можете использовать 'debug_backtrace()' внутри 'CacheService :: cached()' для выключения последнего вызова и получения имени дочернего класса. Я очень советую против этого, потому что это довольно глупо. – FtDRbwLXw6

+0

Хорошо, думал так. Тогда, я думаю, я поеду с этим решением, сделав параметр класса необязательным и вернусь к stacktrace, когда он не будет передан. Спасибо за помощь. – Aistina

0

Попробуйте использовать магию постоянного __CLASS__

EDIT: Как это:

class CacheService { 
    function cached($class, $callback) { 
    // see if function is in cache, otherwise do callback and store results 
    } 
} 


class Base { 
    public static function getAll() { 
    return CacheService::cached(__CLASS__, function() { 
     // get objects from the database 
    }); 
    } 
} 

ДАЛЕЕ EDIT: Использование get_called_class:

class CacheService { 
    function cached($class, $callback) { 
    // see if function is in cache, otherwise do callback and store results 
    } 
} 


class Base { 
    public static function getAll() { 
    return CacheService::cached(get_called_class(), function() { 
     // get objects from the database 
    }); 
    } 
} 
+0

Это будет также возвращать CacheService. – Aistina

+0

Попробуйте, как описано сейчас (он может просто вернуть Base, хотя) – megaflop

Смежные вопросы