2016-07-12 10 views
0

オブジェクトに含まれる値の合計で配列を設定しようとしています。ただし、オブジェクト(この例では「共有」)の1つがオブジェクトに設定されていない場合、操作は次のエラーをスローせずに続行する必要があります。3進演算子が計算中PHP

"[ErrorException]未定義のプロパティ: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) 
     ]; 

オペレータは、他の2つ前のオブジェクト/値を含むすべてのものを、評価しているように見えます。評価された値を最後の「$ ExternalPost-> shares-> count」だけに制限するにはどうすればよいですか?

答えて

2

複数の3値演算子を一緒に使用しないようにロジックを書き換えることをお勧めします。 PHP comparison operators documentation氏は述べています:PHPの三項演算子が左結合されているため、代わりに右結合の、それは他のほとんどの言語であるよう

Note:

It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious:

Example #4 Non-obvious Ternary Behaviour

<?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. 
?> 

これがあります。

1

$ExternalPost->sharesが未定義の場合は、エラーが発生しない限り、操作を続行する必要はありません。これはあなたのような何かにロジックを変更することができ、あなたがそうで$ExternalPost->shares->count

をチェックしている場合に定義する必要があります

((isset($ExternalPost->shares) && $ExternalPost->shares->count) ? $ExternalPost->shares->count : 0) 
あなたがオブジェクトのプロパティまたは配列のキーにアクセスしようとすると、PHPがエラーをスローします
0

それが存在するかどうかを確認するためだけに行っても、存在しません。代わりにproperty_exists()(オブジェクトの場合)またはarray_key_exists()(配列の場合)またはisset()(何でも)を使用してください。これらのメソッドの1つを使用すると、変数/プロパティ/キーが存在しない場合にエラーをスローせずに存在するかどうかをチェックすることができます。

あなたのよう例を書き換えることができます:あなたの元のコードは

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->shares->count) ? $ExternalPost->shares->count : 0) 
+0

'$ ExternalPost-> shares-> count'が' NULL'の場合、 'isset(...)'は 'FALSE'を返します。これは三項演算子に後者の' 0'を返させます。これは元のコードの結果と一致します。私が間違っていない限り? –

0

http://ideone.com/c9bY5o


三条件は括弧との検証をラップしている必要がありますプロパティ、存在を区別するために値と検索された値。

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

http://ideone.com/GKkpZw

オブジェクトを除去reactionsshares特性を有していたことに留意されたいです。


は勧告については、私はあなたがオブジェクトにメソッドを割り当て、合計にその方法を取得代わりに示唆しています。そのため、ある場所で計算を維持し、他のスクリプトでその計算を再利用するだけで済みます。

このようにすれば、データで洗練されたものを他の場所に表示する必要がある場合や、後でオブジェクトや計算に変更や追加を行う場合は、はるかに簡単です。たとえば、投稿に共有がある場合の反応やコメントの合計、または「Up and Down Votes」の追加などです。

ラフレイジーゲッター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; 
    } 
} 

は、だから今、あなたのスクリプトのコードは、あなたはまた、あなたの現在のコードの形式を保持するために__set__get魔法の方法を適用することができ

$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()]; 

http://ideone.com/oqSYNd

ようになり、それが作るとして、それは非常に落胆していますあなたのコードはそれほど簡単ではありません。