Задать вопрос
@Snewer

Как передать аргументы в неизвестную функцию?

Здравствуйте!
Имеется класс, который загружает другой класс в свойство $obj. Далее методом __call из загруженного класса возможен вызов функций. Пока имеется такой код:

public function __call($function, $args){
    $arg_str = '';
    $count = count($args);
    if($count > 0)   for($i = 0; $i <= $count - 1; $i++)  $arg_str .= '$args['.$i.'],';
    $arg_str = rtrim($arg_str, ',');
    eval('$this->obj->'.$function.'('.$arg_str.');');
  }


возможно ли более правильное решение? Спасибо.
  • Вопрос задан
  • 2390 просмотров
Подписаться 1 Оценить Комментировать
Решения вопроса 1
alexey-m-ukolov
@alexey-m-ukolov Куратор тега PHP
Вызвать функцию, название которой находится в переменной, можно несколькими способами:
// Когда аргументы и их количество известно заранее
// Такой вариант мне кажется самым читабельным
// Оборачивать в фигурные скобки не обязательно
// Я это делаю всегда для того, чтобы было видно, что вызов динамический
$this->obj->{$function}($arg1, $arg2)

или
// Подходит как раз для описанного случая
// Аргументы могут быть любыми и передаются в виде массива
call_user_func_array([$this->obj, $function], [$arg1, $arg2]);
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
nazarpc
@nazarpc
Open Source enthusiast
Алексей Уколов почти так написал, вот аналог вашего кода без eval (он почти никогда не нужен):
public function __call($function, $args){
    return call_user_func_array([$this->obj, $function], $args);
}
Ответ написан
Комментировать
akubintsev
@akubintsev
Опытный backend разработчик
Не хочу особо занудствовать, но ваша "магия" никак не соотносится с ООП. Обращаясь к вашему объекту вы должны точно знать, что он может делать, а используя такой __call вы изначально подразумеваете, что на самом деле используете другой объект, в котором сейчас метод есть. А потом кто-то его изменит. И вы не узнаете о том, что ваш объект его использовал неявно.
Лучше чётко прописывать все проксируемые методы в своём классе.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы