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
总是转换为数组?
为什么我的字符串现在是数组?
答案 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