2012-02-13 4 views
2

У меня есть два класса, которые я использую для доступа к двум различным таблицам в моем db. Они оба имеют такой же конструктор, который выглядит следующим образом:PHP - Могу ли я передать имя функции в качестве аргумента функции?

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 столе.

Я немного новичок, и я не думаю, что когда-либо видел что-то вроде того, чего хочу.

ответ

1

Чтобы ответить на ваш вопрос первым: Нет, вы не можете (не прибегая к 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 выглядит как ответ, вы, вероятно, задаете неправильные вопросы!

См: related question

+0

Использование eval не требуется при передаче строки в качестве имени функции. – CBusBus

+0

Почему бы просто не поместить «switch» в конструктор родительского класса и передать строку, чтобы решить, какой dao использовать? Разве это нарушит «открытый принцип»? – JDelage

+0

Кроме того, я не понимаю, как писать родительский конструктор ($ db) 'в дочернем конструкторе. Почему бы просто не написать '$ this-> db = $ db' (и нам вообще не нужен родительский конструктор). На самом деле, у меня есть мой код прямо сейчас, но я надеялся упростить его, имея один конструктор в родительском классе (и ни одного в дочерних элементах). – JDelage

2

Переместите код для создания DAO на фабрику, а затем введите 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-> дб, либо передать, что в заводе через CTOR или переместить создание на фабрику, а также. Это несколько удвоенная ответственность, но терпимая, учитывая, что эта фабрика вращалась вокруг создания диаграмм соавторов, связанных с базой данных.

Кроме того: да, call_user_func(array('ClassName', 'methodName')) будет работать. Смотрите инструкцию для

+0

Что такое завод? – JDelage

+0

@JDelage: проверьте [this] (http://en.wikipedia.org/wiki/Factory_method_pattern). Там есть пример PHP. – FtDRbwLXw6

+0

Спасибо, 'switch' должно было быть очевидно для меня ... – JDelage

1

Есть несколько методов, которые вы можете использовать, если вы чувствуете, что необходимо передать имя функции или действительно саму функцию в качестве параметра функции.

call_user_func($function,$args); 

call_user_func является одной из встроенных функций РНР для вызова методов или функций, которые принимают имя функции и необязательный параметр аргументов.

Функциональность 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*/ 
Смежные вопросы