在foreach循环中,双引号字符串中不会替换变量值

时间:2016-01-19 18:47:53

标签: php mysql

我已经在SO上阅读了几个主题,但它们似乎都没有解决我的问题。我甚至尝试了一些代码示例,但它们不适合我。

我花了几天时间试图解决这个问题,但到目前为止,我已经失败了。我不认为这是一个可变范围的问题,但我可能是错的。由于实际的脚本太长而无法发布,我只会显示我的逻辑,我希望这已经足够了。

主要脚本逻辑:

<?php
require_once General functions
require_once Validator class
require_once DB table setup

function ForValidationRule()
{
}

if($_POST)
{
 validation rules
 if(validations pass)
 {
  variables set
  foreach(loop thru selected tables to create)
  {
    foreach(loop thru table array to build query)
    {
     $sql .= $data . PHP_EOL;
    }
  }
 }
}
?>

这是我测试期间使用的表数组:

$tbl_names = array
(
 "`id_no` INT NOT NULL AUTO_INCREMENT,",
 "`type_id` CHAR(1) NOT NULL,",
 "`abbrev` VARCHAR(30) NOT NULL,",
 "`description` VARCHAR(75) NULL DEFAULT NULL,",
 "PRIMARY KEY (`id_no` ASC),",
 "UNIQUE INDEX `type_id-abbrev` (`type_id` ASC, `abbrev` ASC))",
 "ENGINE = {$engine}",
 "CHARACTER SET {$charset} COLLATE {$dbcoll}",
 "AUTO_INCREMENT = 2",
 "COMMENT = '{$company} {$tbl_name['names']['full']}';"
);

我遇到问题的3个变量是:$ engine,$ dbcoll和$ charset。当我在构建查询之前回显变量时,它们是正确的。当我在构建查询后回显变量时,它们是正确的。但这是构建查询的结果:

CREATE TABLE `tester`.`name_pre-suf`(
`id_no` INT NOT NULL AUTO_INCREMENT,
`type_id` CHAR(1) NOT NULL,
`abbrev` VARCHAR(30) NOT NULL,
`description` VARCHAR(75) NULL DEFAULT NULL,
PRIMARY KEY (`id_no` ASC),
UNIQUE INDEX `type_id-abbrev` (`type_id` ASC, `abbrev` ASC))
ENGINE = 
CHARACTER SET  COLLATE 
AUTO_INCREMENT = 2
COMMENT = 'CEF, Inc. Name Prefixes/Suffixes File';

可以看出,查询中的所有3个变量都是空白的。使用1个变量$ engine,我尝试了几种方法但没有工作。

"ENGINE = {${$engine}}"
"ENGINE = " . $engine
'ENGINE = ' . $engine

谁能看到我做错了什么?如果我硬编码值而不是使用变量,代码可以正常工作。

编辑1: 我在原始逻辑示例中犯了一个错误。在进入任何foreach循环之前设置变量。我已经纠正了逻辑样本。这就是我设置这些变量的方式:

$dbhost = $_POST['dbhost'];
$dbuser = $_POST['dbuser'];
$dbpass = $_POST['dbpass'];
$dbname = $_POST['dbname'];
$dbcoll = str_ToLower($_POST['dbcoll']);
$dbcoll_ary = explode("_", $dbcoll);
$charset = trim($dbcoll_ary['0']);
$engine = 'innodb';
if($charset == 'utf8mb4')
{
 $engine = 'innodb ROW_FORMAT=DYNAMIC';
}

这是我在构建查询之前和之后回显的地方。

echo($engine . PHP_EOL);
echo($dbcoll . PHP_EOL);
echo($charset . PHP_EOL);
   $sql = "CREATE TABLE `$dbname`.`{$tbl_name[$key]['db']}`(" . PHP_EOL;
   foreach(${'tbl_' . $key} as $data)
   {
    $sql .= $data . PHP_EOL;
   } // Closing brace for foreach(${'tbl_' . $key} as $data)
echo($engine . PHP_EOL);
echo($dbcoll . PHP_EOL);
echo($charset . PHP_EOL);
echo($sql . PHP_EOL);
exit();

回显的值是正确的,它们是用户选择的值。

编辑2: 表名和表设置在使用require_once命令包含的表文件中定义。这是表名数组和我用于测试的第一个表数组。

$company = defined('COMPANY_NAME_SHORT') ? COMPANY_NAME_SHORT : '';

$tbl_name = array
(
 'names' => array('db' => 'name_pre-suf', 'full' => 'Name Prefixes/Suffixes File'),
 'tmzn' => array('db' => 'timezones', 'full' => 'Timezones File'),
 'curr' => array('db' => 'currency', 'full' => 'Currency File'),
 'langtyp' => array('db' => 'language_types', 'full' => 'Language Types File'),
 'lang' => array('db' => 'language', 'full' => 'Language File'),
 'cntyp' => array('db' => 'country_types', 'full' => 'Country Types/Sub-Types File'),
 'cntry' => array('db' => 'countries', 'full' => 'Countries'),
 'terri' => array('db' => 'territories', 'full' => 'Territories'),
 'trans' => array('db' => 'translations', 'full' => 'Translations'),
 'langu' => array('db' => 'languages', 'full' => 'Languages'),
 'curry' => array('db' => 'currencies', 'full' => 'Currencies'),
 'dialc' => array('db' => 'dial_codes', 'full' => 'Dialing Codes'),
 'topld' => array('db' => 'tl_domains', 'full' => 'Top Level Domains'),
 'users' => array('db' => 'users', 'full' => 'Users'),
 'usact' => array('db' => 'users_activity', 'full' => 'Users Activity'),
);

$tbl_names = array
(
 "`id_no` INT NOT NULL AUTO_INCREMENT,",
 "`type_id` CHAR(1) NOT NULL,",
 "`abbrev` VARCHAR(30) NOT NULL,",
 "`description` VARCHAR(75) NULL DEFAULT NULL,",
 "PRIMARY KEY (`id_no` ASC),",
 "UNIQUE INDEX `type_id-abbrev` (`type_id` ASC, `abbrev` ASC))",
 "ENGINE = {$engine}",
 "CHARACTER SET {$charset} COLLATE {$dbcoll}",
 "AUTO_INCREMENT = 2",
 "COMMENT = '{$company} {$tbl_name['names']['full']}';"
);

主脚本近600行(包括所有php,html和javascript),而表设置(1个表名数组和所有单独的表数组)文件大约是300行。我可以在SO中附加文件吗?

1 个答案:

答案 0 :(得分:0)

因为这完美无缺:

"(?:<<:--!!(\\d{6})([a-zA-Z ]+))"

我会假设你的所有变量都是空的。检查<?php $engine = "InnoDB"; $dbcoll = "utf8_general_ci"; $charset = "utf8"; $tbl_names = array ( "`id_no` INT NOT NULL AUTO_INCREMENT,", "`type_id` CHAR(1) NOT NULL,", "`abbrev` VARCHAR(30) NOT NULL,", "`description` VARCHAR(75) NULL DEFAULT NULL,", "PRIMARY KEY (`id_no` ASC),", "UNIQUE INDEX `type_id-abbrev` (`type_id` ASC, `abbrev` ASC))", "ENGINE = {$engine}", "CHARACTER SET {$charset} COLLATE {$dbcoll}", "AUTO_INCREMENT = 2", "COMMENT = '{$company} {$tbl_name['names']['full']}';" ); foreach($tbl_names as $value){ echo $value .PHP_EOL; } ?> $charset$engine是否包含与其对应的值。

修改(OP提供的更多信息)

问题在于,当您声明数组时,变量未设置

如果在声明数组后有变量,那么您的代码将无法按预期工作。

$dbcoll

因此,在声明数组之前声明变量。

我会推荐这样的东西。

<?php
//This won't work.
$tbl_names = array(/*..*/);

$engine = "InnoDB";
$dbcoll = "utf8_general_ci";
$charset = "utf8";

?>

使用您的代码段:

<?php
    //Validate the $_POST for valid values...
    $engine = !empty($_POST["engine"]) $_POST["engine"] ? "InnoDB"; 
    $dbcoll = !empty($_POST["dbcoll"]) $_POST["dbcoll"] ? "utf8_general_ci";
    $charset = !empty($_POST["charset"]) $_POST["charset"] ? "utf8";

    $tbl_names = array(/*..*/);
    //Now $tbl_names will have the correct values. 
    //The default ones, or the user submitted ones

?>

问题是你包括你的数组,之前你的变量甚至存在,这就是为什么你需要在设置变量后包含文件。