У меня есть два класса, которые я использую для доступа к двум различным таблицам в моем db. Оба они имеют похожий конструктор, который выглядит так:
function __construct($db) { $this->db = $db; $userDAO = DAO_DBrecord::createUserDAO($this->db); $this->userDAO = $userDAO; }
Другой класс имеет тот же конструктор, за исключением того, что он использует createOtherTableDAO($this->db)
.
Я планирую иметь пару других таких классов, и было бы удобно, если бы они могли наследовать один и тот же конструктор и передать createAppropriateTableDAO
в качестве аргумента.
Чтобы прояснить, в первом случае выше createUserDAO($this->db)
является статической функцией, которая вызывает конструктор в моем классе DAO. Функция в DAO выглядит следующим образом:
public static function createUserDAO($db) { return new DAO_DBrecord($db, 'users'); }
Я использую этот метод, чтобы убедиться, что модель user
может вызывать только DAO в таблице users
.
Я немного новичок, и я не думаю, что когда-либо видел что-то вроде того, чего хочу.
Чтобы ответить на ваш вопрос первым: Нет, вы не можете (не прибегая к evilCode) передать имя функции в качестве параметра. Но: то, что вы хотите архивировать, – это проблема-плакат-ребенок для объектно-ориентированного подхода с использованием наследования.
Вам нужен базовый класс:
class BaseClass { function __construct($db) { $this->db = db; } }
и ваши реализации:
class MyClass extends BaseClass { function __construct($db) { parent::__contruct($db); $this->userDAO = DAO_DBrecord::createUserDAO($this->db); } }
Только для записи: evilCode был бы a) вы могли бы инкапсулировать свою функцию в create_function
которая может использоваться в качестве аргумента. b) вы можете передать имя функции в виде строки в свою функцию, а затем передать ее в eval
в функции приема.
Но помните: когда eval или create_function выглядит как ответ, вы, вероятно, задаете неправильные вопросы!
См .: связанный вопрос
Переместите код, чтобы создать DAOs в Factory, а затем введите DAO вместо того, чтобы жестко связать их с тем, что должны представлять эти классы. Или, скорее, создать различные Шлюзы данных таблицы («классы, которые я использую для доступа к двум различным таблицам») в целом на фабрике, например
class TableDataGatewayFactory … public function create($gatewayName) { switch ($gatewayName) { case 'user': return new TableDataGateway(new UserDao($this->db))); break; default: throw new Exception('No Gateway for $gatewayName'); } } }
Что касается $ this-> db, либо передайте это в Factory через ctor, либо переместите создание в Factory. Это несколько удвоенная ответственность, но терпимая, учитывая, что эта фабрика вращалась вокруг создания диаграмм соавторов, связанных с базой данных.
Кроме того: да, call_user_func(array('ClassName', 'methodName'))
будет работать. См. Руководство для
Существует несколько методов, которые вы можете использовать, если считаете необходимым передать имя функции или, собственно, функцию как параметр функции.
call_user_func($function,$args);
call_user_func – одна из нативных функций Php для вызова методов или функций, которая принимает имя функции и необязательные аргументы.
Функциональность call_user_func (когда это не относится к методам объектов) может быть реплицирована без использования call_user_func, используя переменную со строковым литералом имени функции. Например:
function some_func() { echo "I'm a function!"; } $function = "some_func"; $function(); /*Output: I'm a function!*/
И если вы чувствуете себя авантюристом, вы можете пойти немного дальше и передать функцию закрытия / анонимности вместо имени функции. Например:
$function = function() { echo "I'm another function!"; } $function(); /*Output: I'm another function*/
Вы можете добиться такого поведения, используя: