我正在尝试使用对象中包含的值的总和来设置数组。但是,当在对象中未设置其中一个属性(此示例中为“shares”)时,操作应该继续而不会引发以下错误:
“[ErrorException] Undefined property:stdClass :: $ shares”
我正在尝试使用三元运算符来实现此目的,如下所示:
$array = [strtotime('today midnight') =>
$ExternalPost->reactions->summary->total_count ?: 0 +
$ExternalPost->comments->summary->total_count ?: 0 +
($ExternalPost->shares->count ? $ExternalPost->shares->count : 0)
];
看起来运算符正在评估所有内容,包括其他两个前面的对象/值。如何将评估值限制为最后一个“$ ExternalPost-> shares-> count”?
答案 0 :(得分:2)
我建议重写你的逻辑,这样它就不会同时使用多个三元运算符。 PHP comparison operators documentation说:
注意:强>
建议您避免"堆叠"三元表达式。在单个语句中使用多个三元运算符时,PHP的行为是不明显的:
示例#4非明显的三元行为
<?php // on first glance, the following appears to output 'true' echo (true?'true':false?'t':'f'); // however, the actual output of the above is 't' // this is because ternary expressions are evaluated from left to right // the following is a more obvious version of the same code as above echo ((true ? 'true' : false) ? 't' : 'f'); // here, you can see that the first expression is evaluated to 'true', which // in turn evaluates to (bool)true, thus returning the true branch of the // second ternary expression. ?>
这是因为PHP的三元运算符是左关联的而不是右关联的,就像在大多数其他语言中一样。
答案 1 :(得分:1)
如果未定义$ExternalPost->shares
,则没有理由在没有该错误的情况下继续操作。如果您正在检查$ExternalPost->shares->count
否则,您可以将逻辑更改为:
((isset($ExternalPost->shares) && $ExternalPost->shares->count) ? $ExternalPost->shares->count : 0)
答案 2 :(得分:0)
如果您尝试访问不存在的对象属性或数组键,PHP将抛出错误,即使您只是这样做以检查它是否存在。相反,您应该使用property_exists()
(对于对象),或array_key_exists()
(对于数组)或isset()
(对于任何事物)。使用其中一种方法可以检查变量/属性/键是否存在而不会抛出错误,如果它没有。
您的示例可以重写为:
...
(isset($ExternalPost->shares->count) ? $ExternalPost->shares->count : 0)
答案 3 :(得分:0)
您的原始代码相当于
if ($ExternalPost->reactions->summary->total_count) {
$a = $ExternalPost->reactions->summary->total_count;
} else {
if ($ExternalPost->comments->summary->total_count) {
$a = 0 + $ExternalPost->comments->summary->total_count;
} elseif($ExternalPost->shares->count) {
$a = 0 + $ExternalPost->shares->count
} else {
$a = 0;
}
}
三元条件应包含括号和属性验证,以区分现有值和检索值。
(isset($ExternalPost->reactions->summary->total_count) ? $ExternalPost->reactions->summary->total_count : 0) +
(isset($ExternalPost->comments->summary->total_count) ? $ExternalPost->comments->summary->total_count : 0) +
(isset($ExternalPost->shares->count) ? $ExternalPost->shares->count : 0);
否则使用详细格式,这更容易阅读。
if (isset($ExternalPost->reactions->summary->total_count)) {
$a = $ExternalPost->reactions->summary->total_count;
} else {
$a = 0;
}
if (isset($ExternalPost->comments->summary->total_count)) {
$a += $ExternalPost->comments->summary->total_count;
} else {
$a += 0;
}
if (isset($ExternalPost->shares->count)) {
$a += $ExternalPost->shares->count;
} else {
$a += 0;
}
请注意,该对象已移除reactions
和shares
个属性。
至于建议,我建议您将方法分配给对象并以此方式获取总计。因此,您只需要在一个位置维护计算,并且能够在其他脚本中重复使用它。
这样,如果你想对数据做一些更复杂的事情,需要在别处显示它,或者你决定稍后更改或添加对象或计算,它会更容易。例如,只有当帖子有份额或添加向上和向下投票时,总计反应和评论。
Rough Lazy Getter OOP示例 - 它可以重构为在设置值时计算总数,接受一组值等等。
class ExternalPost
{
private $reactions;
private $comments;
private $shares;
public function __construct(Reactions $reactions = null, Comments $comments = null, Shares $shares = null)
{
$this->reactions = $reactions;
$this->comments = $comments;
$this->shares = $shares;
}
public function getReactions()
{
if (null === $this->reactions) {
$this->reactions = new Reactions;
}
return $this->reactions;
}
public function getComments()
{
if (null === $this->comments) {
$this->comments = new Comments;
}
return $this->comments;
}
public function getShares()
{
if (null === $this->shares) {
$this->shares = new Shares;
}
return $this->shares;
}
public function getTotal()
{
return $this->getReactions()->getTotal() +
$this->getComments()->getTotal() +
$this->getShares()->getCount();
}
}
class Summary
{
private $total_count = 0;
public function getTotalCount()
{
return $this->total_count;
}
public function setTotalCount($total)
{
$this->total_count = $total;
return $this;
}
}
abstract class Summation
{
protected $summary;
public function __construct(Summary $summary = null)
{
$this->summary = $summary;
}
public function getSummary()
{
if (null === $this->summary) {
$this->summary = new Summary;
}
return $this->summary;
}
public function getTotal()
{
return $this->getSummary()->getTotalCount();
}
public function setTotal($total)
{
$this->getSummary()->setTotalCount($total);
return $this;
}
}
class Reactions extends Summation{}
class Comments extends Summation{}
class Shares
{
private $count = 0;
public function getCount()
{
return $this->count;
}
public function setCount($count)
{
$this->count = $count;
return $this;
}
}
所以现在脚本中的代码看起来像
$reactions = new Reactions;
$reactions->setTotal(1);
$comments = null;
/*
$comments = new Comments;
$comments->setTotal(2);
//alternative to using getComments below
*/
$ExternalPost = new ExternalPost($reactions, $comments);
/* $ExternalPost->getReactions()->setTotal(1);
//alternative to defining $reactions above */
$ExternalPost->getComments()->getSummary()->setTotalCount(2);
$ExternalPost->getShares()->setCount(3);
$array = [strtotime('today midnight') => $ExternalPost->getTotal()];
您还可以应用__set
和__get
魔术方法来保留您当前的代码格式,但我们强烈建议不要这样做,因为它会让您的代码更容易理解。