Say I have this HTML:
<html>
<head>
<title>Hello [[USER_FIRST_NAME]]</title>
</head>
<body>
<p>Hi, [[USER_FIRST_NAME]] [[USER_LAST_NAME]]!</p>
<p>[[USER_EMAIL]]</p>
</body>
</html>
I need to preg_replace all those [[FOOBAR]] tokens with values.
End result:
<html>
<head>
<title>Hello John</title>
</head>
<body>
<p>Hi, John Smith!</p>
<p>john#smith.com</p>
</body>
</html>
The php function strtr is a good alternative to preg_replace for your case. Some example:
$tokens = array(
'USER_FIRST_NAME' => 'John',
'USER_EMAIL' => 'john#smith.com',
);
$pattern = '[[%s]]';
$map = array();
foreach($tokens as $var => $value)
{
$map[sprintf($pattern, $var)] = $value;
}
$output = strtr($template, $map);
Basically the same answer as in multiple preg_replace on the same variable. See as well Efficient way to replace placeholders with variables.
No need for regex here:
$data_map = array(
'[[USER_FIRST_NAME]]' => 'John',
'[[USER_LAST_NAME]]' => 'Smith',
'[[USER_EMAIL]]' => 'john#smith.com'
);
$html = <<<HTML
<html>
<head>
<title>Hello [[USER_FIRST_NAME]]</title>
</head>
<body>
<p>Hi, [[USER_FIRST_NAME]] [[USER_LAST_NAME]]!</p>
<p>[[USER_EMAIL]]</p>
</body>
</html>
HTML;
$html = str_replace(array_keys($data_map), array_values($data_map), $html);
You would need to do that in a loop like this:
<?php
$html = ' <html>
<head>
<title>Hello [[USER_FIRST_NAME]]</title>
</head>
<body>
<p>Hi, [[USER_FIRST_NAME]] [[USER_LAST_NAME]]!</p>
<p>[[USER_EMAIL]]</p>
</body>
</html>';
$replacements = array(
'USER_FIRST_NAME' => 'John',
'USER_LAST_NAME' => 'Smith',
'USER_EMAIL' => 'john#smith.com',
);
foreach($replacements as $find => $replace)
{
$html = preg_replace('/\[\[' . preg_quote($find, '/') . '\]\]/', $replace, $html);
}
echo $html;
Maybe you are looking to do something more like this. This has the advantage of replacing all unknown tokens or if you wish you could throw an exception or something.
You could also modify the regular expression to allow for a special escape sequence (on the off chance you ever wanted to include [[ or ]] in an email.)
You could also change your regular expression to '/\[\[(\w+)\]\]/' if you are looking for more strict matching.
<?php
$html = ' <html>
<head>
<title>Hello [[USER_FIRST_NAME]]</title>
</head>
<body>
<p>Hi, [[USER_FIRST_NAME]] [[USER_LAST_NAME]]!</p>
<p>[[USER_EMAIL]]</p>
</body>
</html>';
function replaceTokens($token)
{
$replacements = array(
'USER_FIRST_NAME' => 'John',
'USER_LAST_NAME' => 'Smith',
'USER_EMAIL' => 'john#smith.com',
);
if(isset($replacements[$token[1]]))
{
return $replacements[$token[1]];
}
else
{
return '';
}
}
$html = preg_replace_callback('/\[\[(.*?)\]\]/', 'replaceTokens', $html);
echo $html;
Related
I have the following test.php file, and when I run it, the closing </h1> tag gets removed.
<?php
$doc = new DOMDocument();
$doc->loadHTML('<html>
<head>
<script>
console.log("<h1>hello</h1>");
</script>
</head>
<body>
</body>
</html>');
echo $doc->saveHTML();
Here is the result when I execute the file:
PHP Warning: DOMDocument::loadHTML(): Unexpected end tag : h1 in Entity, line: 4 in /home/ryan/NetBeansProjects/blog/test.php on line 14
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<script>
console.log("<h1>hello");
</script>
</head>
<body>
</body>
</html>
So, why is it removing the tag? It's a string so shouldn't it ignore it?
The only solution that comes to mind is to preg match the script tags, then replace them with a temporary holder like <script id="myuniqueid"></script> and at the end of dom management replace again with the actual script, like this:
// The dom doc
$doc = new DOMDocument();
// The html
$html = '<html>
<head>
<script>
console.log("<h1>hello</h1>");
</script>
</head>
<body>
</body>
</html>';
// Patter for scripts
$pattern = "/<script([^']*?)<\/script>/";
// Get all scripts
preg_match_all($pattern, $html, $matches);
// Only unique scripts
$matches = array_unique( $matches[0] );
// Construct the arrays for replacement
foreach ( $matches as $match ) {
// The simple script
$id = uniqid('script_');
$uniqueScript = "<script id=\"$id\"></script>";
$simple[] = $uniqueScript;
// The complete script
$complete[] = $match;
}
// Replace the scripts with the simple scripts
$html = str_replace($complete, $simple, $html);
// load the html into the dom
$doc->loadHTML( $html);
// Do the dom management here
// TODO: Whatever you do with the dom
// When finished
// Get the html back
$html = $doc->saveHTML();
// Replace the scripts back
$html = str_replace($simple, $complete, $html);
//Print the result
echo $html;
This solution prints clean without dom errors.
Pass LIBXML_SCHEMA_CREATE to loadHTML options. That will fix the issue.
<?php
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML(
'<html>
<head>
<script>
console.log("<h1>hello</h1>");
</script>
</head>
<body>
</body>
</html>',
LIBXML_HTML_NODEFDTD | LIBXML_SCHEMA_CREATE
);
echo $doc->saveHTML();
Another option is to replace </TAG> with <\/TAG>:
<?php
$html = <<<'EOD'
<!DOCTYPE html>
<html>
<head>
<script>
console.log("<h1>hello</h1>");
var foo = '';
var bar = "";
</script>
</head>
<body>
</body>
</html>
EOD;
preg_match_all('/<script\b[^>]*>.*?<\/script>/s', $html, $matches);
$matches = array_unique( $matches[0] );
if( !empty($matches) ) {
foreach ( $matches as $matches__value ) {
$before = $matches__value;
$after = $matches__value;
preg_match_all('/<\/[a-zA-Z][a-zA-Z0-9]*>/', $matches__value, $matches_inner);
$matches_inner = array_unique( $matches_inner[0] );
if( !empty($matches_inner) ) {
foreach($matches_inner as $matches_inner__value) {
if($matches_inner__value === '</script>') { continue; }
$after = str_replace($matches_inner__value, str_replace('/','\/',$matches_inner__value), $after);
}
$simple[] = $after;
$complete[] = $before;
}
}
$html = str_replace($complete, $simple, $html);
}
$DOMDocument = new \DOMDocument();
$DOMDocument->loadHTML($html);
$html = $DOMDocument->saveHTML();
echo $html;
file_get_htm return false, but if i try get data to string, then everything is ok ..
$url = "http://www.dkb-handball-bundesliga.de/de/dkb-hbl/spielplan/spielplan-chronologisch/";
$output = file_get_contents($url);
print_r($output); //this return string
$html = file_get_html($url);
print_r($html); //this return false
i was try with curl, but everything is the same...
if i cgange url for example, everything work ok...
$url='http://www.dkb-handball-bundesliga.de/de/s/spiele/2014-2015/dkb-handball-bundesliga/1--spieltag--bergischer-hc-vs-sg-bbm-bietigheim/';
You will get data from this:
<?php
// put your code here
include_once './simple_html_dom.php';
$html = file_get_html("http://www.dkb-handball-bundesliga.de/");
$links = array();
foreach($html->find('a') as $a) {
$links[] = $a->href;
}
print_r($links);
?>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="ISO-8859-1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>TODO write content</div>
<table>
<tr>
<th>My elements</th>
Hello world 1
Hello world 2
Hello world 3
Hello world 4
Hello world 5
</tr>
</table>
</body>
</html>
<?php
// You need to know the location of the file that you are calling.
include_once './simple_html_dom.php';
$html = file_get_html("http://localhost/PhpHelpers/examples.html");
$links = array();
foreach($html->find('a') as $key => $val) {
$links[$key] = $val;
}
print_r($links);
?>
I'm new to PHP so please bear with me. I'm practicing coding for real situations so I mimicked a database by storing my image paths in an associate array so that I could create a function that would return the path name and thus just call the function to echo out my image.
My problem is it's only returning the last item in my array. I need the function to loop through the array for every item and return the file path so that I can store it in $images and then echo that out where I need to.
CODE:
<?php
$images = array(
array('name' => 'image_00', 'path' => 'images/image-00.jpg'),
array('name' => 'image_01', 'path' => 'images/image-01.jpg'),
array('name' => 'image_02', 'path' => 'images/image-02.jpg')
);
function returnPath($filename, $arr) {
$path = array();
foreach ($arr as $file) {
$path = $file[$filename];
}
return $path;
}
$images = returnPath('path', $images);
?>
<!DOCTYPE html>
<html>
<head>
<title>Images Project</title>
</head>
<body>
<img src="<?php echo $images; ?>"/>
</body>
</html>
The issue is that you're over-writing the $path variable in your returnPath function.
What you want is this:
foreach ($arr as $file) {
$path[] = $file[$filename];
}
Which in turn will give you an array of the paths that you can itterate over like this:
$images = returnPath('path', $images);
<body>
<?php
foreach($images as $image) {
echo '<img src="'. $image .'" />';
}
?>
</body>
I also strongly agree with koala_dev's comment. The function isn't really effective/useful.
Since you already have the $images array, just:
foreach($images as $img) {
echo $img['path'];
}
Or even make the function useful by returning formatted html <img> tags to print to the HTML DOM :-)
just read on Multi dimensional array. its very simple.
<?php
$images = array(
array('name' => 'image_00', 'path' => 'images/image-00.jpg'),
array('name' => 'image_01', 'path' => 'images/image-01.jpg'),
array('name' => 'image_02', 'path' => 'images/image-02.jpg')
);
?>
<!DOCTYPE html>
<html>
<head>
<title>Images Project</title>
</head>
<body>
<?php
for($i=0;$i<sizeof($images);$i++){ ?>
<img src="<? echo $images[$i]['path']; ?>"/>
<?php }?>
</body>
</html>
Okay, so my question is pretty simple. I hope the answer is too.
Let's say I have the following php string:
<!DOCTYPE html>
<html>
<head>
<title>test file</title>
</head>
<body>
<div id="dynamicContent">
<myTag>PART_ONE</myTag>
<myTag>PART_TWO </myTag>
<myTag> PART_THREE</myTag>
<myTag> PART_FOUR </myTag>
</div>
</body>
</html>
Let's say this is $content.
Now, you can see I have 4 custom tags (myTag) with one word content. (PART_ONE, PART_TWO, etc.)
I want to replace those 4 with 4 different strings. Those latter 4 strings are in an array:
$replace = array("PartOne", "PartTwo", "PartThree", "PartFour");
I did this but it doesn't work succesfully:
$content = preg_replace("/<myTag>(.*?)<\/myTag>/s", $replace, $content);
So, I want to search for myTags (it finds 4) and replace it with one entry of the array. The first occurrence should be replaced by $replace[0], the second by $replace[1], etc.
Then, it will return the "new" content as a string (not as an array) so I can use it for further parsing.
How should I realize this?
Something like the following should work:
$replace = array("PartOne", "PartTwo", "PartThree", "PartFour");
if (preg_match_all("/(<myTag>)(.*?)(<\/myTag>)/s", $content, $matches)) {
for ($i = 0; $i < count($matches[0]); $i++) {
$content = str_replace($matches[0][$i], $matches[1][$i] . $replace[$i] . $matches[3][$i], $content);
}
}
One approach would be to loop over each element in the array you want to replace with; replace the words myTag with myDoneTag or something for each one you finished, so you find the next one. Then you can always put back myTag at the end, and you have your string:
for(ii=0; ii<4; ii++) {
$content = preg_replace("/<myTag>.*<\/myTag>/s", "<myDoneTag>".$replace[ii]."<\/myDoneTag>", $content, 1);
}
$content = preg_replace("/myDoneTag/s", "myTag", $content);
With regexes, you could something like this:
$replaces = array('foo','bar','foz','bax');
$callback = function($match) use ($replaces) {
static $counter = 0;
$return = $replaces[$counter % count($replaces)];
$counter++;
return $return;
};
var_dump(preg_replace_callback('/a/',$callback, 'a a a a a '));
But really, when searching for tags in html or xml, you want a parser:
$html = '<!DOCTYPE html>
<html>
<head>
<title>test file</title>
</head>
<body>
<div id="dynamicContent">
<myTag>PART_ONE</myTag>
<myTag>PART_TWO </myTag>
<myTag> PART_THREE</myTag>
<myTag> PART_FOUR </myTag>
</div>
</body>
</html>';
$d = new DOMDocument();
$d->loadHTML($html);
$counter = 0;
foreach($d->getElementsByTagName('mytag') as $node){
$node->nodeValue = $replaces[$counter++ % count($replaces)];
}
echo $d->saveHTML();
This should be the syntax you're looking for:
$patterns = array('/PART_ONE/', '/PART_TWO/', '/PART_THREE/', '/PART_FOUR/');
$replaces = array('part one', 'part two', 'part three', 'part four');
preg_replace($patterns, $replaces, $text);
But be warned, these are run sequentially so if the text for 'PART_ONE` contains the text 'PART_TWO' that will be subsequently replaced.
I am just starting PHP (as in today).
I want to create a customizable menu using a jquery script that can have a variable amount of items.
I am getting an error when i run this.
The error is:
Parse error: syntax error, unexpected T_VARIABLE in /home/s0urc3/public_html/files01/menu.php on line 5
Thanks to Chase for his answer
index.php:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
<?PHP
$script_url="http://files01.s0urc3.ismywebsite.com/jquery/nagging-menu/nagging-menu.js";
$menu_css="http://files01.s0urc3.ismywebsite.com/jquery/nagging-menu/style.css";
$links = array(
array("url" => "http://www.something1.com", "label" => "something"),
array("url" => "http://www.something2.com", "label" => "something2"),
array("url" => "http://www.something3.com", "label" => "something3"),
);
include("menu.php");
?>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
<title></title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" type="text/css" href=".css"/>
</head>
<body>
<?=writeMenu($links, $menu_css, $script_url)?>
</body>
</html>
menu.php:
<?
function writeMenu($links, $script_url, $menu_css){
$menu = '<link href=\"$menu_css\" type=\"text/css\">'
$menu = '<div id="navi">';
$menu .= '<div id="menu" class="default">';
$menu .= '<ul>';
foreach ($links as $item) {
$menu .= "<li>".$item['label']."</li>";
}
$menu .= "</ul>";
$menu .= "</div>";
$menu .= "<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js\" charset=\"utf-8\"></script>";
$menu .= "<script type=\"text/javascript\" src=$script_url charset=\"utf-8\"></script>";
return $menu;
}
?>
Thanks to Chase for his Re-script
Let me say I am not too familiar with jquery, so I will only comment on your php use.
First off, you will need to use quotes around string like this: print("<li><a href=$link_1_url>$link_1_label</a></li>")
Then there is the question why you are using a switch like this and then copying the same thing and adding some. You can easily do it as follows instead:
if ($items >= 1)
{
// print line 1
}
if ($items >= 2)
{
// print line 2
}
if ($items >= 3)
{
// print line 3
}
This will make sure you don't have to copy the same thing over and over again. The same thing can be done with a switch as below, but this code is harder to understand:
$out = "";
switch ($items)
{
case 3:
$out = "line3" . $out;
case 2:
$out = "line2" . $out;
case 1:
$out = "line1" . $out;
print($out);
break;
}
If you are wondering how that works, take a good look and keep in mind that I have only one break statement. This is just harder to understand and less clear, though, so it's just not recommended.
However, as the only thing you are changing each time is a number, you can use the for-loop, which was made for just that purpose:
for ($i = 0; $i < $items; $i++)
{
print("line " . $i);
}
Now you see, that's a lot shorter and easier, yet very clear.
edit: I was missing one thing: the long line of urls you had up there. One thing to learn when you program is to keep some neat whitespace, it's barely even clear that we are talking about a function here. Take a look at my code and yours... mine is readable while yours is not and that's all due to the whitespace I inserted and you didn't... Anyway, you probably you to use an array:
function printMenu ($urls)
{
foreach ($urls as $url)
{
print("<a href='" . $url . "'>Link!</a>");
}
}
// Now you can do:
printMenu(array("url1", "url2", "url3"));
<?
$links = array(
array("url" => "http://www.something1.com", "label" => "something"),
array("url" => "http://www.something2.com", "label" => "something2"),
array("url" => "http://www.something3.com", "label" => "something3"),
);
function writeMenu($links){
$menu = '<div id="navi">';
$menu .= '<div id="menu" class="default">';
$menu .= '<ul>';
foreach ($links as $item) {
$menu .= "<li>".$item['label']."</li>";
}
$menu .= "</ul>";
$menu .= "</div>";
$menu .= "<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js\" charset=\"utf-8\"></script>";
$menu .= "<script type=\"text/javascript\" src=$script_url charset=\"utf-8\"></script>";
return $menu;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<meta name="generator" content="HTML Tidy for Mac OS X (vers 14 February 2006), see www.w3.org">
<title></title>
</head>
<body>
<?=writeMenu($links)?>
</body>
</html>
Ok so i looked over the code so generously supplied by chase an solved my own issue. :D
here is the code of both menu.php and index.php
Menu.php:
<!--
PHP menu by ellisgeek
$email = 'ellisgeek#gmail.com';
$URL = 'http://s0urc3.ismywebsite.com'
Original code by chase on StackOverflow.com
-->
<?
function writeMenu($links, $css){
echo '<link rel="stylesheet" type="text/css" href="$css" media="screen"/>';
echo '<div id="navi"><div id="menu" class="fixed"><ul class=""> ';
foreach ($links as $item) {
echo "<li>".$item['label']."</li>";
}
echo "</ul>";
echo "</div>";
echo "</div>";
}
?>
Index.php:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
<?
$css="style.css";
$links = array(
array("url" => "http://www.something1.com", "label" => "something"),
array("url" => "http://www.something2.com", "label" => "something2"),
array("url" => "http://www.something3.com", "label" => "something3"),
);
include("menu.php");
?>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
<title></title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" type="text/css" href=".css"/>
</head>
<body>
<?=writeMenu($links, $menu_css, $script_url)?>
<p>Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum Lorum</p>
<!--Add lotsa these-->
</body>
</html>
this will write a menu using a ul and a few div's feel free to copy n paste just don't remove the credit comment please.