方法的可选参数,当作为字符串传递时,变成数组
Method's optional parameter, when passed as string, becomes an array
Tl;dr: 在底部
设置:
我有一个 cron 作业调用 PHP 脚本来处理一些后端任务。为简单起见,cron 作业将所有输出重定向到一个日志文件。因为这对我在下面发现的实际问题很重要,所以这里是 cron 作业的净化格式:
15 4 * * * php /usr/local/bin/myScript.php >> /home/$USER/scriptLogs/myScript.log 2>&1
我是 OOP 的新手,我的任务是边学边学,对于 myScript.php
,我正在做一些需要查询数据库以验证数据的数据导入在导入之前,我应该记录每笔交易。我们最近从 5.6 迁移到 7.2,手头的部分任务是在重构时使用 7.2 的新功能。
重构本身就是将所有重复的代码移至类以遵守DRY原则。
以前,它看起来像这样:
<?php namespace CronJobs
use PDO;
use Exception;
class JobAt415 {
private function getDBconnection()
{
// connects to a DB through environment variable set in a config file
return $db;
}
public function query1($parameter1, $parameter2, $inclusionParameter)
{
$sql = "SELECT " . $parameter1 . ", ". $parameter2 . " FROM `foo`.`bar` WHERE " . $inclusionParmeter " IS NOT NULL;";
try
{
$db = $this->getDBconnection();
echo '[' . strftime("%c") . '] Running query 1' . PHP_EOL;
$resultDictionary = $db->query($sql)->fetchall(PDO::FETCH_KEY_PAIR)
return $resultDictionary;
}
catch (Exception $e)
{
echo '[' . strftime("%c") . '] ERRORS ' . PHP_EOL;
echo $e->getMessage();
return null;
}
}
public function query2($parameter1, $parameter3)
{
$sql = "SELECT " . $parameter1 . " FROM `foo`.`bar` WHERE " . $parameter3 " > 0;";
try
{
$db = $this->getDBconnection();
echo '[' . strftime("%c") . '] Running query 1' . PHP_EOL;
$resultDictionary = $db->query($sql)->fetchall()
return $resultArray;
}
catch (Exception $e)
{
echo '[' . strftime("%c") . '] ERRORS ' . PHP_EOL;
echo $e->getMessage();
return null;
}
}
}
Post-重构:
<?php namespace CronJobs
use PDO;
use Exception;
Class DbConnectionFactory {
protected $dbConnection;
public function __construct()
{
$this->dbConnection = $this->createConnection();
}
public function runQuery($sql, ...$queryDescriptor)
{
try
{
$descriptor = $queryDescriptor ? (string) $queryDescriptor : $sql;
echo '[' . strftime("%c") . '] Running query ' . "$descriptor" . PHP_EOL;
$resultPending = $this->dbConnection->query($sql);
echo '[' . strftime("%c") . '] Query successful.' . PHP_EOL;
return $resultPending;
}
catch (Exception $e)
{
echo '[' . strftime("%c") . '] ERRORS ' . PHP_EOL;
echo $e->getMessage();
return null;
}
}
public function runQueryFetchDictionary($sql, ...$queryDescriptor)
{
$description = (string) $queryDescriptor;
$fetchAll = $this->runQuery($sql, $description)->fetchall(PDO::FETCH_KEY_PAIR);
return $fetchAll;
}
// In the JobAt415 class
private function runQuery1()
{
$sql = 'SELECT `parameter1`, `parameter2` FROM `foo`.`bar` WHERE `baz` IS NOT NULL;';
$description = 'p1, p2 :: baz != NULL';
$p1Dictionary = $this->db->runQueryFetchDictionary($sql, $descripton); // $this->db is an instantiation of the DbConnectionFactory class
所以,现在我只是将 SQL 查询作为参数传递,并描述要回显到日志中的查询内容,并且我没有 19 try/catch
块我从这个例子中删除的代码或一堆重复的代码。
不幸的是,当我使用 XDebug 单步执行代码时,可选参数 $queryDescriptor
正在从字符串转换为数组。我尝试了多种传递它、转换它、and/or 定义它并得到相同结果的方法:$queryDescriptor
是一个数组。有一次,将其转换为字符串会返回“Array”的值。
当我查看 PHP website 时,我发现了这个:
Note:
The behaviour of an automatic conversion to array is currently undefined.
强调我的。
我不想要任何转换。那么,我该如何防止呢?有人看到我错过了什么吗?为什么 $sql
字符串不转换为数组,而 $queryDescriptor
总是被转换?
Tl;博士:
为什么我的字符串现在是一个数组?
因为通过添加像 ...$queryDescriptor
这样的参数,您告诉 PHP 可以有无穷无尽的参数。这是因为变量名前面的...
。这就是 PHP 将类型更改为数组的原因。
否则你如何处理可能有数千个参数的数量?
https://secure.php.net/manual/en/functions.arguments.php#functions.variable-arg-list
//You tell PHP that there can be a variable number of parameters by adding '...' in front of the variable name
function foo(...$bar) {
//You get an array holding all the passed parameters
foreach($bar as $arg) {
//By stepping through it you get all the parameters
echo $arg;
}
}
当然也可以通过索引获取参数
$bar[0]; //returns the first passed parameter
Tl;dr: 在底部
设置:
我有一个 cron 作业调用 PHP 脚本来处理一些后端任务。为简单起见,cron 作业将所有输出重定向到一个日志文件。因为这对我在下面发现的实际问题很重要,所以这里是 cron 作业的净化格式:
15 4 * * * php /usr/local/bin/myScript.php >> /home/$USER/scriptLogs/myScript.log 2>&1
我是 OOP 的新手,我的任务是边学边学,对于 myScript.php
,我正在做一些需要查询数据库以验证数据的数据导入在导入之前,我应该记录每笔交易。我们最近从 5.6 迁移到 7.2,手头的部分任务是在重构时使用 7.2 的新功能。
重构本身就是将所有重复的代码移至类以遵守DRY原则。
以前,它看起来像这样:
<?php namespace CronJobs
use PDO;
use Exception;
class JobAt415 {
private function getDBconnection()
{
// connects to a DB through environment variable set in a config file
return $db;
}
public function query1($parameter1, $parameter2, $inclusionParameter)
{
$sql = "SELECT " . $parameter1 . ", ". $parameter2 . " FROM `foo`.`bar` WHERE " . $inclusionParmeter " IS NOT NULL;";
try
{
$db = $this->getDBconnection();
echo '[' . strftime("%c") . '] Running query 1' . PHP_EOL;
$resultDictionary = $db->query($sql)->fetchall(PDO::FETCH_KEY_PAIR)
return $resultDictionary;
}
catch (Exception $e)
{
echo '[' . strftime("%c") . '] ERRORS ' . PHP_EOL;
echo $e->getMessage();
return null;
}
}
public function query2($parameter1, $parameter3)
{
$sql = "SELECT " . $parameter1 . " FROM `foo`.`bar` WHERE " . $parameter3 " > 0;";
try
{
$db = $this->getDBconnection();
echo '[' . strftime("%c") . '] Running query 1' . PHP_EOL;
$resultDictionary = $db->query($sql)->fetchall()
return $resultArray;
}
catch (Exception $e)
{
echo '[' . strftime("%c") . '] ERRORS ' . PHP_EOL;
echo $e->getMessage();
return null;
}
}
}
Post-重构:
<?php namespace CronJobs
use PDO;
use Exception;
Class DbConnectionFactory {
protected $dbConnection;
public function __construct()
{
$this->dbConnection = $this->createConnection();
}
public function runQuery($sql, ...$queryDescriptor)
{
try
{
$descriptor = $queryDescriptor ? (string) $queryDescriptor : $sql;
echo '[' . strftime("%c") . '] Running query ' . "$descriptor" . PHP_EOL;
$resultPending = $this->dbConnection->query($sql);
echo '[' . strftime("%c") . '] Query successful.' . PHP_EOL;
return $resultPending;
}
catch (Exception $e)
{
echo '[' . strftime("%c") . '] ERRORS ' . PHP_EOL;
echo $e->getMessage();
return null;
}
}
public function runQueryFetchDictionary($sql, ...$queryDescriptor)
{
$description = (string) $queryDescriptor;
$fetchAll = $this->runQuery($sql, $description)->fetchall(PDO::FETCH_KEY_PAIR);
return $fetchAll;
}
// In the JobAt415 class
private function runQuery1()
{
$sql = 'SELECT `parameter1`, `parameter2` FROM `foo`.`bar` WHERE `baz` IS NOT NULL;';
$description = 'p1, p2 :: baz != NULL';
$p1Dictionary = $this->db->runQueryFetchDictionary($sql, $descripton); // $this->db is an instantiation of the DbConnectionFactory class
所以,现在我只是将 SQL 查询作为参数传递,并描述要回显到日志中的查询内容,并且我没有 19 try/catch
块我从这个例子中删除的代码或一堆重复的代码。
不幸的是,当我使用 XDebug 单步执行代码时,可选参数 $queryDescriptor
正在从字符串转换为数组。我尝试了多种传递它、转换它、and/or 定义它并得到相同结果的方法:$queryDescriptor
是一个数组。有一次,将其转换为字符串会返回“Array”的值。
当我查看 PHP website 时,我发现了这个:
Note:
The behaviour of an automatic conversion to array is currently undefined.
强调我的。
我不想要任何转换。那么,我该如何防止呢?有人看到我错过了什么吗?为什么 $sql
字符串不转换为数组,而 $queryDescriptor
总是被转换?
Tl;博士:
为什么我的字符串现在是一个数组?
因为通过添加像 ...$queryDescriptor
这样的参数,您告诉 PHP 可以有无穷无尽的参数。这是因为变量名前面的...
。这就是 PHP 将类型更改为数组的原因。
否则你如何处理可能有数千个参数的数量?
https://secure.php.net/manual/en/functions.arguments.php#functions.variable-arg-list
//You tell PHP that there can be a variable number of parameters by adding '...' in front of the variable name
function foo(...$bar) {
//You get an array holding all the passed parameters
foreach($bar as $arg) {
//By stepping through it you get all the parameters
echo $arg;
}
}
当然也可以通过索引获取参数
$bar[0]; //returns the first passed parameter