Необязательный параметр метода при передаче в виде строки становится массивом - PullRequest
0 голосов
/ 12 марта 2019

Tl; dr: внизу

Настройка:

У меня есть задание cron, которое вызывает PHP-скрипт для обработки некоторых внутренних задач.Для простоты задание cron перенаправляет весь вывод в файл журнала.Поскольку это имеет значение для моего фактического вопроса, найденного ниже, вот санированный формат задания cron:

15 4 * * * php /usr/local/bin/myScript.php >> /home/$USER/scriptLogs/myScript.log 2>&1

Я новичок в ООП, и мне поручено изучить его по ходу, идля 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 - массив.В какой-то момент приведение его к строке вернуло значение «Массив».

Когда я проверял PHP-сайт , я обнаружил следующее:


Примечание:

Поведение автоматического преобразования в массив: в настоящее время не определено .


Выделение мое.

Iне хочу никакого преобразованияИтак, как мне это предотвратить?Кто-нибудь видит, чего мне не хватает?Почему строка $sql не преобразуется в массив, а $queryDescriptor всегда преобразуется?

Tl; dr:

Почему моя строка теперь является массивом?

1 Ответ

1 голос
/ 12 марта 2019

Потому что, добавляя такой параметр, как ...$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
...