optimizing setting content of nodes

16 views
Skip to first unread message

Ryan

unread,
Apr 17, 2009, 3:05:35 PM4/17/09
to phpQuery
Hello,

I have an optimization question that I hope someone can help me with.
What I'm trying to do quickly and efficiently is add content to an
existing html file on the fly when my page is being requested. A very
simple example to illustrate this is:

-------------------------------------------------
$doc = phpQuery::newDocument('<ul id="content"></ul>');

$content_string = str_repeat('<li>test', 500);

pq('#content')->html($content_string);

echo $doc;
-------------------------------------------------

From looking at the code, it appears that when I add the
$content_string with the html() function call, the method in
phpQueryObject.php is importing my $content into the DOM by parsing it
first. Since I do not need to interact with this page any further
besides just echo'ing it out, is there any other method I could use
that would just set the innerHTML property of #content to be my
$content_string, but just treat it as a string rather than import it
first as a DOM object? I would like to use phpQuery to set the
content of nodes in my html document, but just would like it to treat
my content as html text to simply substitute in to improve performance
rather than having to go through the DOM first.

Thanks for your help-
Ryan

Tobiasz Cudnik

unread,
Apr 17, 2009, 7:08:53 PM4/17/09
to phpQuery
I understand your concern, but using innerHTML also parses content.
Simplest thing you can do is to insert some unique token inside
#content, get output of DOM and then replace it with your content.
Although such functionality isn't implemented and have to be done
manually.

It could be possible to make it transparent writing proper plugin
which uses comment/cdata. Unfortunately plugins actually can't
overwrite phpQuery methods, so the output would have to be fetched by
dedicated method.

Personally i suggest to cache every phpQuery operation on high traffic
sites.

There's also other possibility - you can insert PHP code inside
#content which prints your string, then save it as file and include
(eval won't be helpful here). QueryTemplates works this way and all
insert functions are able to insert PHP code. Read this wiki page for
more information:
http://code.google.com/p/phpquery/wiki/PHPSupport#PHP_Code_Support

Ryan

unread,
Apr 17, 2009, 9:40:04 PM4/17/09
to phpQuery
Hi Tobiasz,

Thanks for your reply. I was actually trying out inserting PHP code
earlier today, but I ran into an obscure issue where the document
would come out blank depending on the size of the string. I just
looked into it more to try to narrow it down using the below example.
Also, on a side note, I did find a way to use eval without writing it
into a file by adding '?>' to the beginning of my eval string, though
not sure if that's the recommended thing to do:

-------------------------------------------------
$doc = phpQuery::newDocument('<div id="content"></div>');

$content_string = str_repeat('a', 99988);

pq('#content')->php('echo '.var_export($content_string, true));

eval('?>'.$doc->php());
-------------------------------------------------

On my system, I don't get any output from the eval line, but if I
change the str_repeat line to 99987 (1 character less), then I get
output. Looking at the phpQuery.php file, it seems to be caused by
the function markupToPHP() in the first call to preg_replace_callback
(). For some reason, that line is setting $content to NULL if the
length of content is above a certain length. Not sure if it's an
issue with your regexp or with PHP itself or an issue related to my
environment. I am running PHP 5.2.9 on CentOS 5 though I ran the same
below simplified test on PHP 5.2.9 on Windows and got the same results
there too:

-------------------------------------------------
$content = "<div id=\"content\"><php><!-- echo '".str_repeat('a',
99988)."' --></php></div>";

$content = preg_replace_callback(
'@<php>\s*<!--(.*?)-->\s*</php>@s',
create_function('$m',
'return "<'.'?php ".htmlspecialchars_decode($m[1])." ?'.'>";'
),
$content
);

var_dump($content);
-------------------------------------------------

For me, $content is NULL, but if I change the str_repeat to be 99987,
then $content is populated.

Any help you could provide would be appreciated.

Thanks,
Ryan

Tobiasz Cudnik

unread,
Apr 20, 2009, 9:52:10 AM4/20/09
to phpQuery
Interesting point about eval(), thanks! As it goes about length
limitations - seems its caused by lazy modifier (.+?). Changing it to
greedy (.+) fixes limitation, but aggregates matches into one. I'm
afraid that it has to be done by manual parsing instead of regex to
work properly.

But on the other hand - you don't have to push looong string into
markup. Instead of:

$content_string = str_repeat('a', 99988);
pq('#content')->php('echo '.var_export($content_string, true));

just do:

$content_string = str_repeat('a', 99988);
pq('#content')->php('echo $content_string');

And it will work much better/faster. Eval() inherits full scope, just
like include.

I looked only briefly into this. Will take another look later and
probably this will end up as new issue on bugtracker.

Tobiasz Cudnik

unread,
Apr 30, 2009, 4:48:00 PM4/30/09
to phpQuery
Reply all
Reply to author
Forward
0 new messages