创建一个函数来替换从XML文件中获取的字符串

时间:2015-12-07 16:11:50

标签: php xml

我正在创建一个用预定义的常量替换字符串的某些部分的函数,为此我创建了这个函数:

<?php

function ReplaceWithPath($string)
{
    $toReplace = ["~~BASEPATH~~" => ABSPATH, "~~LIBPATH~~" => LIBPATH];

    foreach ($toReplace as $replace => $replacement)
    {
        if (preg_match($replace, $string))
            return str_replace($replace, $replacement, $string);
        else
            continue;
    }
    return false;
}

?>

但由于某些原因,当我使用它时,它不会给我一个正确的结果,而是boolean false

我在配置文件中使用了这样的功能:

<?php

$cfg_file = str_replace("\\", "/", dirname(__FILE__)) . "/web.config.xml";
$cfg = simplexml_load_file($cfg_file);

define("ABSPATH", $cfg->paths->basepath);

require_once 'library/functions/ReplaceWithString.php';
define("LIBPATH", ReplaceWithPath($cfg->paths->libpath));
var_dump(LIBPATH);

?>

有问题的XML文件部分是:

<paths>
  <basepath>E:/projects/php/site/site/</basepath>
  <libpath>~~BASEPATH~~library/</libpath>
  <classpath>~~LIBPATH~~class/</classpath>
  <traitpath>~~LIBPATH~~trait/</traitpath>
</paths>

我需要能够使用~~BASEPATH~~更改ABSPATH的部分,但只返回boolean false

修改

经过测试,我发现数组($toReplace)中有多个常量会导致这种情况失效。为什么要这样做?!?!?!

创建了新功能:

function ReplacePathPart($path)
{
    $replaced = "";
    $toReplace = array(
        '!!BASEPATH!!'=>ABSPATH, 
        '!!LIBPATH!!'=>LIBPATH
    );

    foreach ($toReplace as $replace => $replacement)
    {
        $replaced = str_replace($replace, $replacement, $path);
    }

    return $replaced;
}

修改后的配置文件:

<?php

$cfg_file = str_replace("\\", "/", dirname(__FILE__)) . "/config/web.config.xml";
$cfg = simplexml_load_file($cfg_file);

define("ABSPATH", $cfg->paths->basepath);
require_once 'library/functions/ReplaceWithString.php';
define("LIBPATH", ReplacePathPart($cfg->paths->libpath));
define("CLASSPATH", ReplacePathPart($cfg->paths->classpath));

print ABSPATH . " |abspath<br />";
print LIBPATH . " |libpath<br />";
print CLASSPATH . " |classpath<br />";

?>

输出:

  

E:/ projects / php / site / site / | abspath
  !! BASEPATH !! library / | libpath
  !! BASEPATH !! library / class / | classpath

1 个答案:

答案 0 :(得分:2)

你似乎过分夸大了这种方式。喝一杯咖啡(☕)或阅读这个答案应该可以解决问题:

首先关闭原来的功能:

function ReplaceWithPath($string)
{
    $toReplace = ["~~BASEPATH~~" => ABSPATH, "~~LIBPATH~~" => LIBPATH];

    foreach ($toReplace as $replace => $replacement)
    {
        if (preg_match($replace, $string))
            return str_replace($replace, $replacement, $string);
        else
            continue;
    }
    return false;
}

preg_match()调用中,~将被视为正则表达式字符串的分隔符。因此,在您的字符串中:~~BASEPATH~~~~LIBPATH~~然后您将使用未转义的分隔符which means your regex will fail

foreach循环中的return语句会立即停止函数调用,并且只会替换1 search => replace元素。

搜索字符串并循环遍历替换数组是不必要的。由于str_replace()已经搜索了搜索字符串+,您可以将数组传递给函数:

  

混合str_replace(混合 $ search,混合 $ replace,混合$ subject [,int&amp; $ count])


现在,在第二次尝试中,您可以更接近解决方案,但仍会犯一些逻辑错误:

function ReplacePathPart($path)
{
    $replaced = "";
    $toReplace = array(
        '!!BASEPATH!!'=>ABSPATH, 
        '!!LIBPATH!!'=>LIBPATH
    );

    foreach ($toReplace as $replace => $replacement)
    {
        $replaced = str_replace($replace, $replacement, $path);
    }

    return $replaced;
}

您仍然遍历替换数组,现在使用$path作为源,它将永远不会更改,并且在每次迭代中,您使用替换的字符串覆盖$replaced。所以最后你最终只替换了最后一个search => replace元素。

解决问题的方法很简单:

function ReplacePathPart($path)
{
    $toReplace = array(
        '!!BASEPATH!!'=>ABSPATH, 
        '!!LIBPATH!!'=>LIBPATH
    );    

    return str_replace(array_keys($toReplace), array_values($toReplace), $path);

}

正如我所说str_replace()可以将数组作为参数,因此使用array_keys($toReplace)搜索您的密钥(!!BASEPATH!!!!LIBPATH!!)并将其替换为值({ {1}},ABSPATH),与array_values($toReplace)一起使用。