方法的可选参数作为字符串传递时,将成为数组

时间:2019-03-11 21:45:40

标签: php arrays string type-conversion php-7

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

后重构:

<?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正在从字符串转换为数组。我尝试了多种方法来传递,投射和/或定义它,并获得相同的结果:$queryDescriptor是一个数组。在某一时刻,将其强制转换为字符串将返回“ Array”的值。

当我检查PHP website时,发现了这一点:


  

注意:

     

自动转换为数组的行为当前未定义


强调我的。

我不要任何转换。那么,如何防止这种情况?有人看到我想念的东西吗?为什么$sql字符串不能转换为数组,而$queryDescriptor总是转换为数组?

Tl; dr:

为什么我的字符串现在是数组?

1 个答案:

答案 0 :(得分:1)

由于添加了...$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