Вообще, нет, правда, это всё решение какой-то странной задачи - распарсить SQL в некое AST, а потом собирать обратно, чтобы SQL-сервер его опять распарсил.
Если это камень в мой огород, то поясню. Задача-то как раз не странная: сделать Query Builder, но не write only, а с возможностью доступа к кускам запроса и их изменения. Потому что
вся вот эта х-ня с замыканиями,
х-ня с трейтами и т.д. и т.п. --- это кнэшно красиво смотрится в документации, но не позволяет дорабатывать "построенный" запрос.
Честно это всё решается только через построение более-менее полноценного AST с дальнейшей его обработкой. Так сделано
в том же питоновском SQLAlchemy.
То есть, во-первых, понятно: нужно AST. Во-вторых, понятно, что свой SQLAlchemy на похапэ не написать, т.к. языку похапэ недостаёт выразительных средств.
ОК, будем передавать куски запроса как строки, потому что собирать AST руками из объектов получается крайне многословно (пример из моих unit-тестов):
PHP:
public function testLogicalExpression()
{
$expr = $this->parser->parseExpression(<<<QRY
a and not b or not not c and d or e
QRY
);
$this->assertEquals(
new LogicalExpression(
array(
new LogicalExpression(
array(
new ColumnReference(array(new Identifier('a'))),
new OperatorExpression('not', null, new ColumnReference(array(new Identifier('b'))))
),
'and'
),
new LogicalExpression(
array(
new OperatorExpression('not', null, new OperatorExpression(
'not', null, new ColumnReference(array(new Identifier('c')))
)),
new ColumnReference(array(new Identifier('d')))
)
),
new ColumnReference(array(new Identifier('e')))
),
'or'
),
$expr
);
}
Типа как вместо наследования брать token_get_all, добавлять методы в класс, собирать обратно и делать eval.
Наследование --- вещь статическая, тащемта. Аналогом наследования можно считать создание в базе представления, например. А запросы нам тащемта надо собирать динамически, в зависимости от пользовательского ввода, например.
То есть, по аналогии, тут мы решаем вопрос "как бы добавить метод существующему экземпляру класса", а в похапэ до 5.4.x ответом на этот вопрос было радостное причмокивание.
Ну и чё-то помнится, eval() с добавлением методов используется в том же PHPUnit'е для Mock'ов (с наследованием, впрочем).
Если так глобально задуматься, давно уже нужен более низкоуровневый интерфейс общения с СУБД, когда на вход дается уже формализованная сериализованная структура запроса. Что-то типа handlersocket, но не такое примитивное, но и не настолько низкоуровневое, как bdb.
SQL ещё худо-бедно переносимый, а этот ужас явно переносимым не будет, плюс писать его руками будет невозможно. Ну и парсинг запроса (если его делать не на похапэ, а на Ц) --- копейки по сравнению со всеми остальными накладными расходами.