2016-01-19 34 views
2

我已經在SO上讀過幾個線程,但沒有一個似乎解決了我的問題。我甚至嘗試了一些代碼示例,但它們不適用於我。在foreach循環中雙引號字符串中的變量值不被替換

我已經花了好幾天的時間來解決這個問題,但到目前爲止我失敗了。我不認爲這是一個可變範圍問題,但我可能是錯的。由於實際的腳本太長,我只會顯示我的邏輯,我希望這已經足夠了。

主要腳本邏輯:

<?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個變量是:$發動機,$ dbcoll和$字符集。當我在構建查詢之前回顯變量時,它們是正確的。當我在構建查詢後回顯變量時,他們是正確的。但這是構建查詢的結果:

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 

任何人都可以看到我做錯了什麼嗎?如果我硬編碼值而不是使用變量代碼確實工作正常。

編輯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中附加文件嗎?

回答

0

由於這完美的作品:

<?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,$dbcoll的值是否與它們對齊。

編輯:(由OP提供更多信息)

的問題是,當你宣佈你的陣列,不是變量設置

如果您在聲明數組後聲明瞭變量,那麼您的代碼將無法按預期工作。

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

?> 

使用您的代碼段:

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

?> 

的問題是,你包括你的陣列,以前你的變量,即使存在,這就是爲什麼你需要包括後的變量是文件組。

+0

是的,你是正確的。如果我聲明並設置表格數組文件中的變量,那麼使用這些值。但是,它們不會被查詢循環中的用戶選擇所改變。用戶在腳本運行之前選擇要使用的COLLATE值。 3個變量被設置,因爲我在查詢循環之前和之後回顯它們。他們被設置。 – CharlesEF

+0

@CharlesEF檢查我編輯的答案。 –

+0

我已經聲明並在任何require_once之前的主腳本的最頂部設置了變量。我還聲明並設置了表格數組文件最頂部的變量。這兩種情況都會導致循環中使用的變量值是聲明的值,而不是實際的用戶選擇的值。換句話說,如果用戶選擇「utf8mb4_unicode_ci」,則仍然使用「utf8_general_ci」。 – CharlesEF

相關問題