2016-07-12 8 views
0

개체에 포함 된 값의 합을 사용하여 배열을 설정하려고합니다. 그러나 속성 (이 예제에서 "공유")이 개체에 설정되어 있지 않으면 다음 오류를 throw하지 않고 작업을 계속해야합니다.계산식의 삼항 연산자 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) 
     ]; 

. 평가 된 값을 마지막으로 "$ ExternalPost-> shares-> count"로 제한하는 방법은 무엇입니까?

답변

2

다중 논리 연산자를 함께 사용하지 않도록 논리를 다시 작성하는 것이 좋습니다. 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() (다른 경우)을 사용해야합니다. 이러한 메서드 중 하나를 사용하면 변수/속성/키가 존재하지 않는 경우 오류를 throw하지 않고 존재하는지 여부를 확인할 수 있습니다.

귀하의 예를 다시 작성할 수로 :

... 
(isset($ExternalPost->shares->count) ? $ExternalPost->shares->count : 0) 
+0

'$ ExternalPost-> shares-> count'가'NULL' 인 경우,'isset (...)'는'FALSE'를 반환합니다. 그러면'3' 연산자가 후자 '0'을 반환합니다. 이것은 원래 코드의 결과와 일치합니다. 내가 틀렸다면? –

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

http://ideone.com/c9bY5o


삼항 조건의 괄호 및 검증을 포장해야 속성, 존재를 구분하기 위해 ing 값과 검색 값.

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

그렇지 않으면 읽을 수있는 자세한 정보 형식을 사용하십시오. 개체를 제거하고 reactionsshares 특성을 갖고 있다는

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

참고.


은 추천에 관해서는, 나는 당신이 개체에 대한 방법을 지정하고 합계 그런 식으로 얻을 대신 좋습니다. 따라서 한 위치에서 계산을 유지하고 다른 스크립트에서 다시 계산할 수 있어야합니다.

그런 식으로 데이터로보다 정교한 작업을하고 싶거나 다른 곳에 표시해야하거나 나중에 개체 나 계산에 변경하거나 추가하기로 결정하면 훨씬 쉬울 것입니다 . 게시물에 공유가있을 때의 반응과 의견을 합산하거나 최대/아래로 투표를 합하는 경우를 예로들 수 있습니다.

거친 레이지 게터 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

과 같을 것이다, 그러나 만들면서 그것은 매우 권장하지 않습니다 당신의 코드는 훨씬 덜 쉽게 따라 할 수 있습니다.