How to fix PHP preg_replace() faulty result order? - php

The faulty result I get now is: 17th of July, 2011Today is .
function finclude($file){
include($file);
}
$str = "Today is {include 'date.php'}.";
echo preg_replace("/\{include '(.*)\'}/e", 'finclude("$1")', $str);
date.php :
<?php echo date('jS \of F'); ?>, 2011
Expected result: Today is 17th of July.

function finclude($file){
return include($file);
}
<?php return date('jS \of F'); ?>
Result isn't expected because You print date, then finclude return null, then you print "Today is "+finclude

What you call faulty in your result order is actually caused by the execution order of your statements:
echo preg_replace("/\{include '(.*)\'}/e", 'finclude("$1")', $str);
Will start the output (echo) and then call the preg_replace function. In which you make use of the e - eval modifier to execute code, namely the function finclude.
So finclude get's executed earlier than preg_replace will return it's result.
So if finclude does output on its own, it will be displayed in front of the result of preg_replace.
Knowing this is half the solution to your problem. It's much likely you didn't intend this output order (your expected result differs) and you just wanted to make finclude return a value instead of outputting something. To convert output into a return value you can make use of an output buffer:
function finclude($file){
ob_start();
include($file);
return ob_get_clean();
}
$str = "Today is {include 'date.php'}.";
echo preg_replace("/\{include '(.*)\'}/e", 'finclude("$1")', $str);
This will ensure that every output within finclude will be returned as a return value instead.
That done you can re-use existing code/includes that normally outputs within your search and replace operation. However using the e modifier always is dangerous and it normally should be prevented. So take care.

i think you need to put <?php return date('jS \of F'); ?> in date.php

Related

How to use substr in php to ignore accented characters?

I am working on a php code as shown below which prints H
echo substr("Hello world",0, 1);
Now, I have an accented Ĥ in Ĥello. The following code prints �.
echo substr("Ĥello world",0, 1);
Problem Statement:
I am wondering what changes I should make in the second echo statement above with Ĥello world as the string so that it prints H instead of �.
Note: I want the second echo statement to return H not Ĥ. Only H
I have used the following code but it seems to return Ĥ not H
echo mb_substr("Ĥello world",0, 1);

PHP Convert Full Date To Short Date

I need a PHP script to loop through all .html files in a directory and in each one find the first instance of a long date (i.e. August 25th, 2014) and then adds a tag with that date in short format (i.e. <p class="date">08/25/14</p>).
Has anyone done something like this before? I'm guessing you'd explode the string and use a complex case statement to convert the month names and days to regular numbers and then implode using /.
But I'm having trouble figuring out the regular expression to use for finding the first long date.
Any help or advice would be greatly appreciated!
Here's how I'd do it in semi-pseudo-code...
Loop through all the files using whatever floats your boat (glob() is an obvious choice)
Load the HTML file into a DOMDocument, eg
$doc = new DOMDocument();
$doc->loadHTMLFile($filePath);
Get the body text as a string
$body = $doc->getElementsByTagName('body');
$bodyText = $body->item(0)->textContent; // assuming there's at least one body tag
Find your date string via this regex
preg_match('/(January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}(st|nd|rd|th)?, \d{4}/', $bodyText, $matches);
Load this into a DateTime object and produce a short date string
$dt = DateTime::createFromFormat('F jS, Y', $matches[0]);
$shortDate = $dt->format('m/d/y');
Create a <p> DOMElement with the $shortDate text content, insert it into the DOMDocument where you want and write back to the file using $doc->saveHTMLFile($filePath)
I incorporated the helpful response above into what I already had and it seems to work. I'm sure it's far from ideal but it still serves my purpose. Maybe it might be helpful to others:
<?php
$dir = "archive";
$a = scandir($dir);
$a = array_diff($a, array(".", ".."));
foreach ($a as $value) {
echo '</br>File name is: ' . $value . "<br><br>";
$contents = file_get_contents("archive/".$value);
if (preg_match('/(January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}(st|nd|rd|th)?, \d{4}/', $contents, $matches)) {
echo 'the date found is: ' . $matches[0] . "<br><br>";
$dt = DateTime::createFromFormat('F jS, Y', $matches[0]);
$shortDate = $dt->format('m/d/y');
$dateTag = "\n" . '<p class="date">' . $shortDate . '</p>';
$filename ="archive/".$value;
$file = fopen($filename, "a+");
fwrite($file, $dateTag);
fclose($file);
echo 'Date tag added<br><br>';
} else {
echo "ERROR: No date found<br><br>";
}
}
?>
The code assumes the files to modify are in a directory called "archive" that resides in the same directory as the script.
Needed the two different preg_match lines because I found out some dates are listed with the ordinal suffix (i.e. August 24th, 2005) and some are not (i.e. August 24, 2005). Couldn't quite puzzle out exactly how to get a single preg_match that handles both.
EDIT: replaced double preg_match with single one using \d{1,2}(st|nd|rd|th)? as suggested.

strtotime conversion with variable error

I am getting wrong output i.e. 1194908400
None of this is working i.e. I tried to put double quotes around variable, tried without quotation marks. result is same and wrong.
$d='07-11-13';
echo $d;
echo strtotime($d);
echo "<br>";
echo strtotime("$d");
After a few checks, the error is actually NOT in the format you're passing, but rather on the way you're passing it.
What you should do is just replace "13" with "2013":
strtotime("07-11-2013");
output: 1383778800
echo strtotime("2013-11-07");
output: 1383778800
echo strtotime('07-11-13');
output: 1194908400
The problem is you need to specify a 4 digit year, so that strtime can fully work out which date format you are using. With 07-11-13 it probably thinks you are using 2007-11-13.
Change it to 07-11-2013 and you will get the correct answer.
$d='07-11-13' is wrong, Try this
$d='2013-11-13';
echo $d;
echo strtotime($d);
echo "<br>";
echo strtotime("$d")
strtotime() will accept:
m/d/y
d-m-y
With / it expects month/day and with - it expects day-month.

php preg_match grab out

<script type="text/javascript"><!--
Vertical1_437 = "false-2010";
ShowAdHereBanner1437 =" true";
RepeatAll1437 = "true";
NoFollowAll1437 ="true";
//-->
</script>
I'm trying to get the 2010 part out of the false-2010.
i want it to echo 2010 only..
Thanks for the help.
this was what i started with and got stuck
<?php
$get2010 = preg_match('/\<!--(.*?)-->/', $get2010, $m);
echo $m[1];
?>
and oh.. the 2010 is a randomly generated number... it changes.
preg_match('!Vertical1_437\s*=\s*"\D+(\d+)"!', $get2010, $m);
echo $m[1];
This assumes it's always the RHS of Vertical1_437. I am also assuming you have that block of HTML code as a string in $get2010.
It may be helpful if you could be more specific about what data is dynamic and what is static. If Vertical1_437 and false are static and the 2010 part is the only dynamic part, then this should work:
preg_match{'#(.*Vertical1_437.*false-)(\d{1,4})(.*)#', $get2010, $m);
echo $m[2];
Mine assumes that "2010" is a digit that is 1-4 digits, you can adjust that in the {1,4} part.
This should do it for the given example. If some of that other text is dynamically generated, then There will probably be something to change.

strange ob_start() behaviour - double output

ob_start() doesn't seem to be stopping any output so when I flush the buffer it's doubling up
<?php
ob_start();
echo "Text..... <br />";
echo ob_get_flush();
?>
Outputs
Text.....
Text.....
But I was expecting
Text.....
Any ideas ?
Thanks
Remove the echo on the last line.
ob_get_flush() implicitly prints the stored output and also returns it so you're printing it out twice.
You may have confused ob_get_flush() with ob_get_clean()
try:
<?php
ob_start();
echo "Text..... <br />";
ob_get_flush();
?>
from http://php.net/manual/en/function.ob-get-flush.php
Flush the output buffer, return it as a string and turn off output buffering
Flush the output means: it sends the output to the browser or the commandline.
return the string means: it returns the string, so you can store the flushed string in a variable. And since you're echoing this string you get the output a second time.

Categories