Php foreach循环中双引号字符串中未替换变量值

Php foreach循环中双引号字符串中未替换变量值,php,mysql,Php,Mysql,我在这里读了好几篇文章,但似乎没有一篇能解决我的问题。我甚至试过一些代码示例,但它们对我不起作用 我花了几天的时间试图弄明白这一点,但到目前为止我失败了。我不认为这是一个可变范围的问题,但我可能错了。由于实际的脚本太长,我将只显示我的逻辑,我希望这是足够的 主脚本逻辑: <?php require_once General functions require_once Validator class require_once DB table setup function ForVali

我在这里读了好几篇文章,但似乎没有一篇能解决我的问题。我甚至试过一些代码示例,但它们对我不起作用

我花了几天的时间试图弄明白这一点,但到目前为止我失败了。我不认为这是一个可变范围的问题,但我可能错了。由于实际的脚本太长,我将只显示我的逻辑,我希望这是足够的

主脚本逻辑:

<?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;
    }
  }
 }
}
?>
我遇到的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中附加文件吗?

,因为这非常有效:

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

?>
因此,在声明数组之前先声明变量

我推荐这样的东西

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

?>

使用您的代码段:

<?php
    $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';
    }

    //if you set your $tbl_name array here, it will work.
    include("table_names.php");

   $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)

?>


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

是的,您是正确的。如果我在表数组文件中声明并设置变量,那么将使用这些值。但是,它们不会被查询循环中的用户选择更改。用户在脚本运行之前选择要使用的COLLATE值。设置这3个变量是因为我在查询循环之前和之后回显它们。我已经在主脚本的最顶端声明并设置了变量,在任何require_之前。我还声明并设置了表数组文件顶部的变量。这两种情况都会导致循环中使用的变量值是声明的值,而不是实际的uers选定值。换句话说,如果用户选择“utf8mb4\u unicode\u ci”,则仍将使用“utf8\u general\u ci”。这正是我试图解释的,如果您有默认值,则必须在用户提交值后重新声明数组。检查我的新更新。是的,在$\u POST验证之后和查询循环运行之前,我确实为用户选择的值设置了相同的变量。换句话说,我确实将变量值设置为用户选择的值,并且我可以在查询循环运行之前和之后回显它们。变量确实包含用户选择的值,但仍然使用声明的值。我没有看到你想说的话吗?我根本不声明表数组,因为它们位于使用require_once命令加载的表数组文件中。没关系,我让它工作了。我不得不将DB表设置文件分成两页。1页的表名数组包含在主脚本的最顶端。另一个页面是在建议的位置包含的表定义数组,在定义变量后,变量值替换似乎只在包含页面时发生一次。
<?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

?>
<?php
    $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';
    }

    //if you set your $tbl_name array here, it will work.
    include("table_names.php");

   $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)

?>