preg_replace_callback question

A long time ago, I acquired a preg_replace script that inserts numerical ID’s in paragraph tags of articles stored in a database. For example, the first paragraph tag will have id=“1”, while the sixth paragraph has id=“6”.

$c = 1;
$r = preg_replace('/(<p( [^>]+)?>)/ie', '"<p\2 id=\"" . $c++ . "\">"', $Article);
$Article = $r;

But I’m now getting an error message: Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead

The following script kills the error message - but it doesn’t insert any ID’s.

$c = 1;
$r = preg_replace_callback('~<p([^>]*)>~i', function($res) use (&$c){
    return '<p'.$res[1].' id="'.$c++.'">';
}, $Article);

Also, do you know how I can modify the script so that the last paragraph includes class=“Last”? So if an article has ten paragraphs, the last paragraph will look like this:

[p id=“10” class=“Last”]

Thanks.

For the first half… does it return id=“” or just no id attribute at all? (If the former, your variable reference is going wrong; if the latter, your pattern isnt matching.)

I feel like you should be using CSS definitions instead of PHP to accomplish the second half of this.

You can target the last paragraph in a series (e.g.)

<div>
<p>asdf</p>
<p>asdf</p>
<p>asdf</p>
<p>asdf</p>
<p>asdf</p>
</div>

If you do the below code, it’ll target the last paragraph. Basically the same as using a class. Browser support is universal at this point (older IE has trouble but IE9+ is really all you need to worry about nowadays)

div p:last-child{background:red;}

It returns no ID attribute at all.

Thanks for the tip about using CSS to focus on the last paragraph; I didn’t know you could do that.

However, in the particular instance, I want to use str_replace to include some content before the last paragraph. If I’m not mistaken, I can’t do that with CSS.

I should probably go back to square one, and start from scratch. All I want to do is insert numerical ID’s (and one class) in paragraph tags in articles stored in a database table. The original script I acquired was a preg_replace. It worked at first, but later started throwing errors, so I was told I needed to upgrade it to preg_replace_callback. However, I recently learned that the callback function is needed only for the “e function,” or something like that.

[quote=“Chavista, post:4, topic:100175, full:true”]
However, in the particular instance, I want to use str_replace to include some content before the last paragraph. If I’m not mistaken, I can’t do that with CSS.

[/quote]Correct.

I copy-pasted your code, but it worked for me, exactly as expected.

<?php

$Article = '
<div>
<p>asdf</p>
<p>asdf</p>
<p>asdf</p>
<p>asdf</p>
<p>asdf</p>
</div>
';

$c = 1;
// $r = preg_replace('/(<p( [^>]+)?\>)/ie', '"<p\2 id=\"" . $c++ . "\">"', $Article);
$r = preg_replace_callback('~<p([^>]*)>~i', function($res) use (&$c){
    return '<p'.$res[1].' id="'.$c++.'">';
}, $Article);
$Article = $r;

echo $Article;

You must have some other problem elsewhere in your code.

Wow, I guess that answers my question. If it works for you, I must just be doing something wrong. I’ll play with it some more and figure it out. Thanks!

P.S. However, does anyone now how to modify it so the last paragraph has a numerical ID plus a class=“Last”?

Well what are you doing with “class=‘Last’” that isnt CSS driven?

I want to use str_replace to insert some content before the last paragraph of every article.

You could probably use a negative lookahead. (Match a “p” tag that isn’t followed by any subsequent “p” tag.)

~<p[^>]*>(?!<p[^>]*>)~i

That being said, if you find yourself having to do a lot of manipulations, consider using DOMDocument instead. Browsers allow all sorts of strange HTML, and sometimes a regex just isn’t up to the task.

Or, even better, try inserting this content during your template rendering rather than manipulating the result after the fact.

I’ll have to do some research on DOMDocument and Template Rendering…

Wikipedia lists some web template engines @ http://en.wikipedia.org/wiki/Comparison_of_web_template_engines One of the engines listed is PHP, which is what I’m using. But I don’t understand what “template rendering” is.

Looking at http://documentation.magnolia-cms.com/display/DOCS/My+first+template my guess is that template rendering is a way to make a page display what you want it to?

And DOMDocument appears to work sort of like a PHP include, right? At first I thought I’d have to convert my pages to XML, but it says it works with HTML, too.

http://php.net/manual/en/class.domdocument.php
http://www.binarytides.com/php-tutorial-parsing-html-with-domdocument/