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


Creating a function to replace strings that have been gotten from an XML file

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

<?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>

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

编辑

经过测试,我发现数组($toReplace)中有多个常量,这是导致此操作不起作用的原因。为什么它会DIS?!?!?!

创建新功能:

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

你似乎想得太多了。喝一杯咖啡(☕)或者阅读这个答案应该可以解决问题:

首先使用您的原始功能:

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~~中,您就有了未标注的分隔符,这意味着您的正则表达式将失败。

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

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

混合str_replace(mixed$search,mixed$replace,mixed$subject[,int&$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!!),并将其替换为值(ABSPATHLIBPATH),这是使用array_values($toReplace)得到的。