这是我上一个问题的后续问题。
Run a function without a parameter but needed a variable outside of the function - PHP
我收到了这个答案
function foo($arg1 = null, $arg2 = null) {
// if they are not set retrieve from a session
$arg1 = ($arg1 !== null) ? $arg1 : $_SESSION['arg1'];
// rinse repeat.
}
所以我想,也许我可以通过阻止在每个函数上调用相同的变量来减少代码行。
我想出了这个。
function foo($arg1 = $_SESSION['user_id'], $arg2 = $_SESSION['campaign_id']) {
//do something
}
不幸的是,我收到了这个错误。
Parse error: syntax error, unexpected T_VARIABLE
是否有理由导致这一结果?我只是将 null 替换为具有值的变量。
有没有办法分配一个函数,该函数的参数已经是一个值,而不是分配一个空值?
P.S。
我尝试使用echo $campaign->getName()
输出数据,因此调用该函数时没有提供参数。
所以我试图调用类似这样的函数
function foo($arg1 = $_SESSION['user_id'], $arg2 = $_SESSION['campaign_id']) {
//do something
}
如果没有任何方法可以一遍又一遍地调用同一个变量。
任何帮助将不胜感激。 :)
答案 0 :(得分:8)
不要尝试(它甚至不能正常工作),使用正确的DI(依赖注入)并将外部(全局)变量作为参数传递:
// functions should be deterministic — require the arguments in favour of using dynamic defaults
function foo($arg1 /* require it */, $arg2 = 1 /* static scalars as default is no problem */) {
// your code
}
foo($_SESSION["user_id"]); // always pass dynamic arguments, don't fetch them in the function
除了所谓的静态标量之外,不可能使用其他任何默认值。这些是文字(字符串,整数等),常量和(自PHP 5.6起)对这些文字/常量的操作。
因此...
两年多前我有同样的好主意,并提交了一份错误报告...... https://bugs.php.net/bug.php?id=60544
今天我认为这不是一个好主意。语言默认值应该是静态的。我怀疑那些设计PHP的人没有他们的理由。
但还有一种方法......
这里唯一的解决方法是使用常量。
function foo($arg = ARG) {
var_dump($arg);
}
在您确定该值不再发生变化的那一刻,请在第一次调用函数之前定义常量:
define("ARG", $_SESSION["user_id"]);
然后您可以稍后通过foo();
调用它。
这可能是由于这里对常量进行惰性评估所致。
这种方法的缺点是你必须定义一次常量,然后它会在其余的脚本运行时保持不变。
但我仍 强烈推荐 。它具有苛刻性,并且有很大的缺点。
您已经向我们展示了如何做到这一点:
$arg1 = ($arg1 !== null) ? $arg1 : $_SESSION['arg1'];
这绝对是正确的方法。如果你真的想这样做。
但你仍然不应该那样做。您正在从函数中访问全局范围(超全局)。
语言设计师没有实现这种可能性的原因之一就是为什么我们不应该试图以任何方式绕过常量或全局范围访问来解决这个问题在功能中。
你真的应该正确使用依赖注入,并通过参数将外部(全局)值传递给函数。 (参见 tl; dr 部分中的示例)
您提出的这种类型的代码很容易导致难以调试的代码,因为人们可能不会期望真正的函数可以访问全局状态。
这就是为什么函数应该具有给定输入的确定性输出(除非它们明确地被认为是非确定性的,例如读取文件的函数),这大大提高了可测试性和可移植性。
答案 1 :(得分:6)
你不能。
您只能将文字分配给函数默认值,即在运行时无法更改的常量值。这意味着,"actual strings"
,数字(42
),硬编码数组([1, 2, 3]
),NULL
。而不是$variables
,function() {}
或其他可能在运行时更改的内容。
你也不应该。
如果你的功能取决于用户ID和广告系列ID,你应该将它们传递给你的功能,而不是依赖他们在SESSION,因为你不知道他们是否实际上在那里!。
不要依赖全局。
为什么不将参数传递给函数?它需要它们,不是吗?您是否希望以下功能在没有参数的情况下工作?
add($x, $y)
仅仅因为这些参数来自SESSION,数据库或世界以外的其他参数?
没有。函数需要两个参数,因此,要求和给出两个参数。
答案 2 :(得分:1)
我对你有坏消息,以较短的形式并不总是更好。这主要是因为你将$ _SESSION值称为常量,这并不是很好。 一个好的,可靠的代码更长,因为所有的检查和验证有助于避免不必要的错误。这基本上是你需要做的:
function foo($arg1 = null, $arg2 = null) {
// if condition
if (!$arg1 && isset($_SESSION['arg1']))
$arg1 = $_SESSION['arg1'];
// tenary condition
$arg2 = (!$arg2 && isset($_SESSION['arg2'])) ? $arg2 : $_SESSION['arg2'];
}
如果你真的想要,你可以寻找一些能够通过几个字母来缩短这段代码的东西,但它并没有太大的不同。所有这些验证都是必须,不应忽略。
答案 3 :(得分:1)
查看上一个问题,我猜你有很多需要广告系列ID和用户ID的方法。我建议您将广告系列ID和用户ID传递给Campaign类的构造函数。然后你可以调用任何方法,并始终可以访问它们:
<?php
$campaign = new Campaign($db, $_SESSION['user_id'], $_SESSION['campaign_id']);
class Campaign {
private $db;
private $user_id;
private $campaign_id;
public function __construct($db, $user_id, $campaign_id) {
$this->db = $db;
$this->user_id = $user_id;
$this->campaign_id = $campaign_id;
}
public function getName() {
$query = $this->db->prepare("SELECT name FROM campaign WHERE campaign_id = :campaign_id AND user_id = :user_id");
$status = $query->execute(array(':campaign_id' => $this->campaign_id, ':user_id' => $this->user_id));
return ($query->rowCount() == 1) ? $query->fetchObject()->name : false;
}
}