I honestly have little clue what facts are relevant to this issue, so I'll go from the beginning.
I have bits of text that I'd like to format Markdown-style urls in before plugging into a template, but I don't want them to be wrapped in <p>'s or any other block-level tags.
To do this, I worked my way through the PHP Markdown code, isolated the stuff needed for the url formatting and threw the functions together into a file called 'MarkdownUrl.php' in a folder called 'functions' at my include path.
I'll post that code at the bottom.
For now, let's test it:
<?php
require_once 'functions/MarkdownUrl.php';
$text = "Hello, world. [This is a link.](http://www.google.com)";
echo MarkdownUrl($text);
?>
Output:
Hello, world. This is a link.
So far so good.
I also have a file called 'loader.php' at the include path. It contains a class autoloading function which it registers with spl_autoload_register()
and another function called loadFunc()
which will require_once
a php file from the 'functions' directory according to the name it's passed. The latter is what matters here.
<?php
function loadFunc($funcName)
{
if (!function_exists($funcName)) {
require_once 'functions/' . $funcName . '.php';
}
}
function loadClass($className)
{
if (!class_exists($className, false)) {
$classPath = str_replace('_', '/', $className);
require_once 'classes/' . $classPath . '.php';
}
}
spl_autoload_register('loadClass');
?>
Ignoring the 'whys' and 'wherefores' of including code in this manner for the moment, the following should be effectively equivalent to the test code I posted earlier, right?
<?php
require_once 'loader.php';
loadFunc('MarkdownUrl');
$text = "Hello, world. [This is a link.](http://www.google.com)";
echo MarkdownUrl($text);
?>
And, yet... output:
Hello, world. [This is a link.](http://www.google.com)
No errors are issued on running the above.
And, I have confirmed that the function MarkdownUrl()
is being called (at least, a test echo
I inserted at the top of the function fired).
Yet, the output is unformatted. WTF?
A couple I'm-not-sure-if-these-matter-at-all details: shared web host, include path specified via php.ini file in directory the test script runs in.
Contents of MarkdownUrl.php:
<?php
$nested_brackets_depth = 6;
$nested_url_parenthesis_depth = 4;
$no_entities = false;
function doAnchors_inline_callback($matches) {
$whole_match = $matches[1];
$link_text = $matches[2];
$url = $matches[3] == '' ? $matches[4] : $matches[3];
$title =& $matches[7];
$url = encodeAttribute($url);
$result = "<a href=\"$url\"";
if (isset($title)) {
$title = encodeAttribute($title);
$result .= " title=\"$title\"";
}
$result .= ">$link_text</a>";
return $result;
}
function encodeAttribute($text) {
#
# Encode text for a double-quoted HTML attribute. This function
# is *not* suitable for attributes enclosed in single quotes.
#
$text = encodeAmpsAndAngles($text);
$text = str_replace('"', '"', $text);
return $text;
}
function encodeAmpsAndAngles($text) {
global $no_entities;
#
# Smart processing for ampersands and angle brackets that need to
# be encoded. Valid character entities are left alone unless the
# no-entities mode is set.
#
if ($no_entities) {
$text = str_replace('&', '&', $text);
} else {
# Ampersand-encoding based entirely on Nat Irons's Amputator
# MT plugin: <http://bumppo.net/projects/amputator/>
$text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
'&', $text);;
}
# Encode remaining <'s
$text = str_replace('<', '<', $text);
return $text;
}
function MarkdownUrl($text) {
global $nested_brackets_depth, $nested_url_parenthesis_depth;
$nested_brackets_re =
str_repeat('(?>[^\[\]]+|\[', $nested_brackets_depth).
str_repeat('\])*', $nested_brackets_depth);
$nested_url_parenthesis_re =
str_repeat('(?>[^()\s]+|\(', $nested_url_parenthesis_depth).
str_repeat('(?>\)))*', $nested_url_parenthesis_depth);
$text = preg_replace_callback('{
( # wrap whole match in 1ドル
\[
('.$nested_brackets_re.') # link text = 2ドル
\]
\( # literal paren
[ \n]*
(?:
<(.+?)> # href = 3ドル
|
('.$nested_url_parenthesis_re.') # href = 4ドル
)
[ \n]*
( # 5ドル
([\'"]) # quote char = 6ドル
(.*?) # Title = 7ドル
6円 # matching quote
[ \n]* # ignore any spaces/tabs between closing quote and )
)? # title is optional
\)
)
}xs','doAnchors_inline_callback', $text);
return $text;
}
?>
1 Answer 1
That happens because you have different variable scopes in your cases.
In first case your variables are defined in global scope, thus $nested_brackets_depth = 6;
and other vars defined in MarkdownUrl.php
are visible for markdown functions
In other case - that variables are defined in function that includes the file scope, so they are not visible inside the functions.
The solution: change markdown file header to
global $nested_brackets_depth = 6;
global $nested_url_parenthesis_depth = 4;
global $no_entities = false;
Btw, it is a great sample why global
is evil and why defining/accessing the variables in global scope is evil too.
-
Of course! Well, with a minor change (inserting
global $nested_brackets_depth, $nested_url_parenthesis_depth, $no_entities;
rather than attempting to initialize values in theglobal
declarations).mutus– mutus2011年08月16日 00:30:14 +00:00Commented Aug 16, 2011 at 0:30 -
Adding that this would probably be avoidable if I'd kept it encapsulated in a class rather than lazily hacking it together into procedural code.mutus– mutus2011年08月16日 00:39:45 +00:00Commented Aug 16, 2011 at 0:39