1
\$\begingroup\$

I'm creating a Q&A website, Something like SO. Now I need to print a "check" icon (to specify accepted answer) next to every answer. Now there are some conditions:

  • Is the current user logged?
  • Is the current user the author of the question?
  • Is there any accepted answer?

And some other cases.

Actually, I implemented that. But I did it using a lot of nested if-statement and seems to me really unoptimized. Now I want to know is there any better algorithm to write this code?

$results = $stm->fetchAll(PDO::FETCH_ASSOC);       // Fetching all answers

foreach ($results as $result){

    if ($_SESSION['id'] == $author_id){            // User is logged
        if($result['id'] == $AcceptedAnswerId){    // There is accepted answer
            $AcceptAnswerIcon = "<a href='#'>
                                    <i style='color: green;' class='fa fa-check'></i>
                                 </a>";
        } else {                                   // There isn't accepted answer
            $AcceptAnswerIcon = "<a href='#'>
                                    <i style='color: gray' class='fa fa-check'></i>
                                 </a>";
        }
    } 

    elseif ($_SESSION['id'] !== $author_id) {      // User isn't logged
        if($result['id'] == $AcceptedAnswerId){    // There isn accepted answer
            $AcceptAnswerIcon = "<i style='color: green;' class='fa fa-check'></i>";
        } else {                                   // There isn't accepted answer
            $AcceptAnswerIcon = null;
        }
    }

    else {
        $AcceptAnswerIcon = null;
    }


// ... I will use $AcceptAnswerIcon in here and mix it with answer structure


} // End of "foreach" block             
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Extract Duplication to Function

You could try to extract some of the duplication:

getCheckIconHTML($color) {
    return "<i style='color: " . $color . ";' class='fa fa-check'></i>";
}

Now all the check icon HTML is in one place, which also makes it easier to change.

But the HTML really doesn't only depend on the color, but it also matters if it is clickable or not, so lets add that as well:

getCheckIconHTML($color, $isClickable) {
    $checkIcon = "<i style='color: " . $color . ";' class='fa fa-check'></i>";
    if ($isClickable) {
        $checkIcon = "<a href='#'>" . $checkIcon . "</a>";
    }
    return $checkIcon;
}

Improve the ifs

Now, the foreach would look like this, which is already better:

foreach ($results as $result){

    if ($_SESSION['id'] == $author_id) {            // User is logged
        if ($result['id'] == $AcceptedAnswerId) {
            $AcceptAnswerIcon = getCheckIconHTML('green', true);
        } else {
            $AcceptAnswerIcon = getCheckIconHTML('grey', true)
        }
    } else {      // User isn't logged
        if ($result['id'] == $AcceptedAnswerId) {
            $AcceptAnswerIcon = getCheckIconHTML('green', false);
        } else {
            $AcceptAnswerIcon = null;
        }
    }
}

But now that we have the function, we can also restructure the ifs to get this:

$isUserLoggedIn = ($_SESSION['id'] == $author_id);
if ($result['id'] == $AcceptedAnswerId) { // There is accepted answer
    $AcceptAnswerIcon = getCheckIconHTML('green', $isUserLoggedIn);
} else {
    $AcceptAnswerIcon = $isUserLoggedIn ? 
            getCheckIconHTML('grey', true) : null;            
}

Misc

  • you don't need the $_SESSION['id'] !== $author_id check in the elseif. You already checked it in the if, so you know that the user is not logged in. If the last else is entered, something went wrong.
  • variable names should start with a lower-case letter.
  • your spacing is sometimes off.
  • I would move the code that checks if a user is logged in into a user class or something. If you just have checks like this all over the place, it will be hard to change the functionality later on.
\$\endgroup\$
2
  • \$\begingroup\$ But why you said "variable names should start with a lower-case letter" ? I have seen that kind of naming already in some projects... \$\endgroup\$
    – Alex
    Commented Jan 12, 2016 at 17:08
  • \$\begingroup\$ @Alex ok, it seems that I was wrong to state it that absolutely. The zend style guide for example demands lower-case variables, the PSR guide however does not (it does require consistency though, so either all your variables should start with an upper-case character or none; I would suggest the second, as it's way more common). \$\endgroup\$
    – tim
    Commented Jan 12, 2016 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.