флейм

crocodile2u

http://vbolshov.org.ru
У меня значительно более прикладной вопрос. Надо было давно его задать, и, может быть, не здесь - да как-то руки не доходили...

вот код:

PHP:
<?php

$pdo = new PDO('mysql:host=localhost;', 'root', null, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
$pdo->query("CREATE DATABASE IF NOT EXISTS pdotest");
$pdo->query("USE pdotest");
$pdo->query("CREATE TABLE IF NOT EXISTS test (id INT NOT NULL AUTO_INCREMENT, name VARCHAR(255), PRIMARY KEY (id))");

$pdo->query("INSERT INTO test (name) VALUES ('n1'), ('n2'), ('n3')");

$s = $pdo->query("SELECT * FROM test");

$s->setFetchMode(PDO::FETCH_KEY_PAIR);

echo "foreach (PDOStatement as ROW) output:\n";
foreach ($s as $key => $row) {
	var_dump($key, $row);
}

$s->execute();
echo "PDOStatement->fetchAll() output:\n";
var_dump($s->fetchAll());

$pdo->query("DROP DATABASE pdotest");

?>
Вот что этот код выводит:
-----------------------------------
foreach (PDOStatement as ROW) output:
int(0)
array(1) {
[1]=>
string(2) "n1"
}
int(1)
array(1) {
[2]=>
string(2) "n2"
}
int(2)
array(1) {
[3]=>
string(2) "n3"
}
PDOStatement->fetchAll() output:
array(3) {
[1]=>
string(2) "n1"
[2]=>
string(2) "n2"
[3]=>
string(2) "n3"
}
-----------------------------------

Замечаете разницу? Вот и возникает вопрос - баг или фича? С моей точки зрения - баг.
 

tony2001

TeaM PHPClub
predator
>я вот не понимаю в чём сложность

начало хорошее.

> - пхп разбирает код каким-то образом и исполняет его в последствии через
> свои сишные либы для каждой конструкции пхп есть свой аналог на си

если предположить, что получится транслировать PHP в С, то мы получим "аналог" на С, который будет работать именно так, как работает его "оригинал" на PHP - один в один.
и весь смысл этой трансляции потеряется, т.к. в PHP большинство потерь именно из-за его удобства для пользователя.
в то же время C - это "ассемблер с понятным интерфейсом", что предполагает собой неограниченное кол-во оптимизаций.

>вобщем разговоры о фантазиях и бессмысленности мне кажутся некорректными

вот здесь следовало бы закончить.
эта фраза хорошо сочетается с первой.

>но разработчики-то люди должно-быть опытные, должны сказать
>реально-ли это

разработчики уже ответили "нет", но этот ответ не устроил.

-~{}~ 11.05.08 01:13:

crocodile2u
Этот вопрос лучше всего задавать в internals@ и надеяться на то, что кто-то знает ответ (или на то, что Wez снизойдёт и ответит, но это уже малореально).
Хотя судя по тому, что этому коду уже 4 года, это 1) явно так и задумывалось; 2) всех устраивает; 3) не будет меняться из-за обратной совместимости.
 

С.

Продвинутый новичок
для каждой конструкции пхп есть свой аналог на си
В общем случае неверно. Каждую конструкцию ПХП надо прогнать по целому комплексу сишных либ и модулей. ПХП уже сам откомпилирован и делает это за тоже самое время, что будет делать твое откомпилированное приложение. Разница лишь в чтении самой ПХП конструкции. Максимум, на чем ты съэкономишь - чтение команд, скорость их исполнения останется такой же.
 

AmdY

Пью пиво
Команда форума
predator
хочешь С, строй свой движок на pecl и других расширениях, там уже есть многое, а в стандартной постаке включено всё необходимое.
и не нужно чтобы другие языки нервно курили - я за мир и многообразие.
 

Vijon

Новичок
Прошу прощения, если мой вопрос окажется оффтопом....

У меня есть некоторые, на мой взгляд, достаточно интересные исходники... Скажем, генератор сложных селективных запросов или методика построения сложных HTML-вью... Могут ими заинтресоваться наверху...:)?
 

AmdY

Пью пиво
Команда форума
не жмись, да ознакомиться здесь, мне очень интересна тема про "сложных HTML-вью"
 

Vijon

Новичок
Вот... Извиняюсь, что длинно, но в сети этого нет...


О формировании представлений в РНР.

Прежде всего, о начальных условиях.

Во-первых, имеется некий источник данных. Это может быть хэш или индексный массив, числовая последовательность, объект, инкапсулирующий реляционный запрос. Ключевой особенностью источника данных является то, что он представляет из себя матрицу, то есть, некий двухмерный объект. При этом, матрица может быть вырожденной: горизонтальным вектором, вертикальным вектором или даже таким странным образованием, как вертикальный 0-мерный вектор (см. ниже).

Во-вторых, имеется некий, если так можно выразиться, класс-парсер нижнего уровня. Экземпляр данного класса представляет из себя кусок HTML-кода и некоторое количество методов, позволяющих упомянутый код модифицировать. При этом, важнее всего наличие у класса-парсера нижнего уровня таких возможностей как: вставка текста по метке вида {SomeVariable}; изъятие блока, то есть, некоего куска кода, ограниченного, к примеру, тэгами комментария.

Насколько известно автору, существуют готовые парсеры (Smart). Однако, вообще-то говоря, не составляет ни малейшего труда написать подобный класс самостоятельно (что автор собственно и сделал).

Формулировка задачи. Требуется представить источник данных в HTML-формате.

Общий алгоритм формирования подобного представления состоит в следующем.

Из HTML-кода, внутри которого нужно сформировать требуемое представление, извлекается блок-шаблон сериализируемого HTML-элемента (строка или ячейка HTML -таблицы, опция списка и так далее...)

Затем, в цикле с шаблона сериализируемого элемента делается рабочая копия, и в рабочую копию вставляются все элементы соответствующей строки источника данных. Если источник данных представляет из себя вышеупомянутый вертикальный 0-мерный вектор, то в рабочую копию не вставляется вообще ничего, то есть, мы имеем категорию классов-представлений, которую можно условно назвать Repeater-ами. Иначе говоря, мы просто размножаем некий HTML-элемент заданное количество раз, без модификации.

Далее, рабочая копия сериализируемого элемента вставляется обратно в основной HTML-код. Цикл повторяется столько раз, сколько строк в источнике данных. Если в источнике данных только одна строка, то мы получаем класс-представление под условным названием Blank. В этом случае, роль сериализируемого элемента играет весь имеющийся HTML-код.

Совершенно очевидно, что формирование HTML-представления вышеописанным образом не зависит от конкретной структуры источника данных, по-скольку организовать циклы по его строками и столбцам без явного обращения к тем и другим - не является чем-то особо сложным.

Используя, например, в качестве источника данных объект-оболочку реляционного запроса (самый интересный случай), можно воспользоваться функциями РНР, типа mysql_list_fields, для получения списка всех полей данного запроса.

Таким образом, вид класса-представления зависит: во-первых, от типа источника данных; во-вторых, от формата представления (бланк, таблица, список...); но не зависит от конфигурации и содержимого данного конкретного экземпляра источника данных (количества строк и столбцов в матрице, значений ее элементов). То есть, если мы хотим представить, к примеру, реляционный запрос в виде таблицы, то неважно, что это будет за запрос, сколько в нем будет полей и как они будут называться.

Но есть одно «но». Что если часть элементов матрицы-источника является некой достаточно сложной функцией от других ее элементов? В принципе, подобную проблему можно решить на уровне источника данных, сформировав последний нужным образом. Однако, это тема для отдельного разговора. На уровне же класса-представления, автор решает данную проблему следующим способом...

Имеется базовый или стандартный, если угодно, класс-представление, формирующий представление источника данных определенного типа в определенном формате. При этом, к вышеописанному алгоритму формирования представления добавляется одна важная деталь. После заполнения очередной рабочей копии сериализируемого элемента всеми элементами текущей строки источника данных, вызывается некий метод (ParseExtras), которому, в частности передаются упомянутые рабочая копия и текущая строка. В базовом классе данный метод пуст, то есть, не делает вообще ничего.

В случае необходимости сгенерировать представление для источника данных со сложновычисляемыми значениями элементов, создается класс-представление, наследующий базовому. Во вновь созданном пользовательском классе, вышеупомянутый метод ParseExtras переопределяется таким образом, чтобы в каждую получаемую им рабочую копию вставлялись элементы, являющиеся сложными функциями от других элементов текущей строки.

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

Теперь к вопросу о том, какими собственно должны быть базовые классы-представления. Казалось бы, совершенно очевидно: есть некий источник данных, скажем, реляционный запрос, есть некий тип представления, например, таблица, вот и имеем базовый класс.

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

Например, таблица заказов, выглядящая следующим образом: строка с датой, затем, строки всех заказов, приходящихся на эту дату и так далее... Причем, вышеописанное представление - далеко не самое сложное.

Создавать базовые классы для каждого подобного типа представления автор счел бесперспективным. В качестве альтернативы, автором была разработана описанная ниже модель Parsers-Serialiser, каковая модель обладает очень высокой вариативностью и позволяет сформировать представление практически любой степени сложности.

Модель создания представлений Parsers-Serialiser, собственно, и опирается на две разновидности классов: Parser-ы и Serialiser.

Главными особенностями классов Parser-ов является то, что они...

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

Во-вторых, что очень важно, классы Parser-ы возвращают не только рабочую копию сериализируемого элемента, но и динамическое имя метки, в которую эту копию нужно вставить. Так, если в старых классах имя метки для вставки задавалось раз и навсегда (например, {ROW-Customer}), то в Parser-ах данное имя является, в общем случае, функцией от значений элементов текущей строки источника данных.

Функция класса Serialiser состоит в том, чтобы взять несколько классов-парсеров (неважно какого типа) и на их основании сформировать общее представление.

Например, в вышеупомянутом случае с таблицей заказов, мы имеем два Parser-а. В первом, источник данных - реляционный запрос, содержащий выборку заказами, а метка вставки меняется динамически, в зависимости от значения поля «ДатаЗаказа». Во-втором, источник данных - последовательность дат требуемого диапазона, а метка вставки - константа.

Передав оба Parser-а Serialiser-у, мы получим требуемую таблицу.

Проблема нестандартных элементов в источнике данных решается в данной модели так же, как и в предыдущей, то есть вызовом метода ParseExtras и передаче ему рабочей копии сериализируемого элемента и текущей строки источника данных.
 

HraKK

Мудак
Команда форума
ой какой-то бред... или я что-то недопонял?
 

Gas

может по одной?
Vijon
я бы как обычно - циклы, ифы и подобные конструкции, которые поддерживают smarty-style шаблонизаторы.
Не нравится такой подход - тогда есть blitz или xslt, а разных велосипедов написано великое множество, новый обсуждать врят-ли стоит.
 

AmdY

Пью пиво
Команда форума
в смарти, например - вложение
{foreache from=$data item="subData"}
{foreache from=$subData item="subSubData"}
{/foreach}
{/foreach}
в xslt это ещё проще и эллегантнее
 

Vijon

Новичок
Мой велосипед выглядит примерно так (таблица 2)...

$Parsers["Notes"]=new DataParser($dsNotes, "ROW-Note", "ROW-DeadlineNotes");
$Parsers["Notes"]->ParseNameField="DeadlineID";

$Parsers["Deadlines"]=new DataParser($dsDeadlines, "ROW-Deadline", "ROW-DayEvents");
$Parsers["Deadlines"]->TimeFormat="%HH:%MM";
$Parsers["Deadlines"]->ParseNameField="DeadlineDate";

$Parsers["Days"]=new DataParser($dsDays, "ROW-Day");
$Parsers["Days"]->DateFormat="%dd.%mm.%yyyy, {WeekDayName}";

$Serialiser=new Serialiser($Parsers, "Days(Deadlines(Notes))", $this->GetNameView());
$Serialiser->Bind();
$Serialiser->Template->PrintHTML();

А теперь сравните с тем объемом и с той сложностью кода, который бы пришлось писать с циклами, ифами или xslt, да умножьте на несколько десятков, а то и сотен подобных представлений в большом проекте...

-~{}~ 11.05.08 22:29:

2 AmdY

Во-первых, логику от представления желательно все же отделять.

Во-вторых, есть, например, списки с различной конфигурацией и масса других представлений, которые никамим Смартом и ХСЛТ не построить... Ну или это будет настолько громоздко... Я же говорю об универсальной модели построения представлений любой сложности и любой конфигурации, причем, с чрезвычайно малыми затратами.

И кстати, все же неплохо бы для начала, понять и обсудить идею собеседника, а уже потом говорить про бред, велосипеды и прочие самокаты... Но это - по желанию, разумеется...
 

AmdY

Пью пиво
Команда форума
интересно было бы посмотреть на сами шаблоны. как данные ты получаешь уже понятно, просто мы тебе писали как их одеть в html
я пытаюсь сам сделать универсальные списки, но пока никаких продвижек нету и у меня только одна мысль - заюзать xslt, он преднозначен для таких вещей, но пока не хочется
поэтому мне твоя идея очень интересна
 

Vijon

Новичок
Я пишу html-болванку со всеми сериализируемыми html-блоками в единственном экземпляре. Каждый сериализируемый блок ограничивается тэгами комментария соответствующей конфигурации...

<!-- BEGIN ROW-Customer -->

<!-- END ROW-Customer -->

Блоки могут быть вложенными или независимыми друг-от-друга.

Метки для полей имеют вполне традиционный формат: {DeadlineID}

Для вставки внутренних блоков во внешний также используются метки...

{_ROW-DayEvents-{DeadlineDate}}

В общем, объем дополнительной разметки в html очень мал и весьма нагляден.

Код, который все это строит, я уже показывал выше.
 

Gas

может по одной?
Vijon
Код который ты привёл - обёртка для построения нужных тебе графических примитивов, сам вывод сосредоточен в printHTML, который уже передаёт данные активному шаблону или рулит пасивным, а в нём что - в нём циклы, if'ы, smarty или голый php. Подобные вещи есть у большинства, это всё равно что сказать: я вот юзаю для работы с mysql не голые mysql_* ф-ции, а объект и это удобно. Спорить с этим никто не будет, это действительно так и почти все поступают так-же, только не стоит выдавать это за инновацию.

И кстати, все же неплохо бы для начала, понять и обсудить идею собеседника
holywars на тему шаблонизаторов здесь предостаточно, в них перемалывалось всё.
 

Vijon

Новичок
printHTML - это примитивный метод, состоящий из одного единственного оператора: print. Все HTML-представление строится методом Bind экземпляра класса Serialiser.

Еще раз повторяю. У меня есть

1. html-болванка с сериализируемыми блоками в единственном экземпляре и минимумом разметки.

2. Код, приведенный выше.

При помощи этих средств я могу построить представление любой сложности.

Вы можете то же самое? Если нет, тогда звыняйтэ, но это таки инновация...
 

AmdY

Пью пиво
Команда форума
чем это лучше http://phpclub.ru/paste/index.php?show=2071
а, ты просто формируешь ещё массив, который содержит поля для вывода, если хочешь могу переписать под это услоие, но влом, да и не так универсатьно как кажется.
у меня похожая схема - извлечения данных, указание полей для вывода и что с ними дополнительно делать, вот только я тормознул, что не сделал вложенных списков. но эта система не удовлеторяет всех моих потребностей
кстати $Parsers["Days"]->DateFormat="%dd.%mm.%yyyy, {WeekDayName}"; вот это и называется неотделённая логика от представления
 

Vijon

Новичок
Какой массив???

Еще раз...

1. Я пишу болванку.

2. Для каждого сериализируемого элемента создаю экземпляр Парсера. Как правило, это стандартные классы.

3. Передаю все Парсеры Сериалайзеру.

4. Распечатываю результат.

Я не говорю, что того же нельзя добиться другими средствами. Весь вопрос в затратах. Мой код, и РНР и ХТМЛ, краток логичен и прозрачен. Логика отделена от представления стопроцентно. Универсальность кода - максимальная. Привязки РНР к ХТМЛ вообще нет. То есть, я могу использовать один и тот же код для нескольких болванок... Ограничений по сложности - никаких. Представление может быть сколько угодно сложным... И так далее...
 

HraKK

Мудак
Команда форума
Vijon
Это все очень прикольно. Только такх или подобных приколов дофига, и мне лично они не нравятся я не буду вдаватся почему, потому что это отходит от формата топика. Твой вопрос - бред. Хочешь сделай из этого екстеншен и юзай на здоровье. А автора пхп тут не причем)
 

AmdY

Пью пиво
Команда форума
Вынесите плиз это в отдельный топик, а то здесь ему действительно не место, но тема стоящая, только реализация мне не нравится, разгребусь со своими вопросами обосную
 
Сверху