1

It's not a problem in fact, but I would like to know if it is possible to optimise the code below.

It's a simple code to show the star rating mark which is in the db.

I searched and tried with @foreach, but can't figure it out.

Code:

<span class="review-stars" style="color: #1e88e5;">
<!-- ////////////// STAR RATE CHECKER ////////////// -->
    @if($review->rate <= 0)
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
    @elseif($review->rate === 1)
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
    @elseif($review->rate === 2)
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
    @elseif($review->rate === 3)
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
    @elseif($review->rate === 4)
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star-o" aria-hidden="true"></i>
    @elseif($review->rate >= 5)
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
    @endif
    <!-- ///////////////////////////////////////////// -->
</span>

When $review->rate <= 0 enter image description here

When $review->rate === 3 enter image description here

When $review->rate >= 5 enter image description here

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Guilhem V
  • 361
  • 2
  • 7
  • 16

5 Answers5

4

I think that's all you need to do. No loops needed. Just make sure the rate value is between 0 and 5 (inclusive) before passing it to the view.

{!! str_repeat('<i class="fa fa-star" aria-hidden="true"></i>', $review->rate) !!}
{!! str_repeat('<i class="fa fa-star-o" aria-hidden="true"></i>', 5 - $review->rate) !!}
Faramarz Salehpour
  • 591
  • 1
  • 3
  • 14
  • Still slightly repetitive, but much simpler to comprehend for the inexperienced developer versus your previous method. +1. Very clean now. – mickmackusa Nov 25 '17 at 14:50
3

Don't Repeat Yourself. Loop 5 times and write a condition to check if the star should be empty.

Code: (Demo: https://3v4l.org/Tj31J )

$review = (object)['rate' => 3];
for ($i = 0; $i < 5; ++$i) {
    echo '<i class="fa fa-star' , ($review->rate <= $i ? '-o' : '') , '" aria-hidden="true"></i>';
}

Output:

<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>

I don't code in Laravel, correct me if this syntax is flawed:

@for ($i = 0; $i < 5; ++$i)
    <i class="fa fa-star{{ $review->rate <= $i ? '-o' : '' }}" aria-hidden="true"></i>
@endfor

If you want to incorporate half-empty (aka half-full) stars, just add another condition. The same design logic applies, add one more condition to check if the star should be halved. Here is a full battery of valid ratings tested:

Code (See the Demo for verbose output: https://3v4l.org/r4c6R )

$reviews = [
    (object)['rate' => 0],
    (object)['rate' => .5],
    (object)['rate' => 1],
    (object)['rate' => 1.5],
    (object)['rate' => 2],
    (object)['rate' => 2.5],
    (object)['rate' => 3],
    (object)['rate' => 3.5],
    (object)['rate' => 4],
    (object)['rate' => 4.5],
    (object)['rate' => 5]
];
foreach ($reviews as $review) {
    for ($i = 0; $i < 5; ++$i) {
        echo '<i class="fa fa-star' ,
            ($review->rate == $i + .5 ? '-half' : '') ,
            ($review->rate <= $i ? '-o' : '') ,
            '" aria-hidden="true"></i>';
        echo "\n";
    }
    echo "\n";
}

If you don't understand the inline conditional syntax, google is only a click away.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • 1
    I can't believe that this simple answer wasn't provided in the recommended dupe link or the dupe link that that question was closed with. – mickmackusa Nov 25 '17 at 13:51
  • This worked perfectly but I don't understand the code, and how can I do if I want to add half star? like if the mark is 3.5, the code should be:` ` – Guilhem V Nov 25 '17 at 16:27
  • @LaynomGraphic I've added a new version that includes half stars. Both methods obey the fundamental programming philosophy of Don't Repeat Yourself (DRY). There are only two types of actions in my process: looping and inline conditionals If either of these are foreign to you, please catch yourself up and research them. – mickmackusa Nov 25 '17 at 20:35
  • https://laracasts.com/discuss/channels/general-discussion/blade-if-else-on-single-line – mickmackusa Nov 25 '17 at 20:54
3

You can do it by following code

@foreach(range(1,5) as $i)
    @if($rating >0)
        @if($rating >0.5)
            <i class="fa fa-star"></i>
        @else
            <i class="fa fa-star-half-o"></i>
        @endif
    @else
        <i class="fa  fa-star-o"></i>
    @endif
    <?php $rating--; ?>
@endforeach
0

Try this way:

<i class="fa fa-star{{ $review->rate <= 0 ? '-o' : '' }} aria-hidden="false"></i><!-- First case is for 0 and 1 case or empty and filled star -->
<i class="fa fa-star{{ $review->rate >= 2 ? '-o' : '' }} aria-hidden="false"></i>
<i class="fa fa-star{{ $review->rate >= 3 ? '-o' : '' }} aria-hidden="false"></i>
<i class="fa fa-star{{ $review->rate >= 4 ? '-o' : '' }} aria-hidden="false"></i>
<i class="fa fa-star{{ $review->rate >= 5 ? '-o' : '' }} aria-hidden="false"></i>
Tpojka
  • 6,996
  • 2
  • 29
  • 39
  • I see that your post has been downvoted, and rightly so. I look at this answer and wonder how you have nearly 4000 rep points. I mean, first it doesn't work, but the logic is just silly. Where is the explanation with your code only answer? Please remove this post as it is completely unadvisable and will only waste readers' time. – mickmackusa Nov 25 '17 at 20:43
  • @mickmackusa Hm, what don't you understand (in first place) from this code and I will gladly help you understand. All five icon classes should be shown. Checked. Fill those only needed by rate number. Checked. I would really like to see where this is not working and link would be more than appreciated. To OP Have you tested this one? – Tpojka Nov 25 '17 at 22:04
  • Have YOU tested this one? At no point are you writing a filled star to the page. You are only writing `-o` (empty stars). About aria, it doesn't "fill the stars", ref: https://stackoverflow.com/q/31107040/2943403 ...besides, even if this did deliver the desired result, it is not optimized -- it is verbose. You may upvote my answer if you find it educational. – mickmackusa Nov 25 '17 at 22:12
  • @mickmackusa Take a break. Not even, this works perfectly. What's the problem? In five HTML lines with ternary operator it works like your 20-30 (how many?) lines code. HTML of rating system is not something need to be dynamic. Chill. What is point of link of aria? You seems really confused. :( – Tpojka Nov 25 '17 at 22:18
  • Well, I've dumbed this down for you as much as I can to show you that your code doesn't work. Go to the proposed dupe link under the question and notice how no one is writing a variable aria value - this is because changing the aria value does not change the star. As long as you leave this answer on the page you will be confusing readers and teaching incorrect code to anyone who doesn't double check the manual. Perhaps in time you will gain more downvotes and come to your senses. – mickmackusa Nov 25 '17 at 22:23
  • P.s. my 20-30 lines of code are used to demonstrate every possible rating. Within any given project, my method can be written in just 3 lines. I think it is not me who needs a break. – mickmackusa Nov 25 '17 at 22:31
  • @mickmackusa Very usefull when in code is checking for identification with integer, but ok. Now is optimized but still with 5 lines. :D – Tpojka Nov 25 '17 at 22:36
  • 1
    @mickmackusa About Silly™ logic, what part there you don't understand with 10k points? :P – Tpojka Nov 25 '17 at 23:00
  • I'm not going to waste anymore of my Sunday morning on you. I have been crystal clear about what is wrong with your answer. If you still don't understand what is wrong, read my comments over and over until it sinks in. Then read fontawesome's resources. Then read up on fundamental best practices of coding/php. Anyone who cannot fathom the benefits of using loops and conditionals either needs to research more or give up coding. The lack of care / understanding displayed in your answer penalizes handicapped people. You may have the last word if you like, because I'm done. – mickmackusa Nov 25 '17 at 23:58
  • tldr; (10 more to go...) – Tpojka Nov 26 '17 at 00:07
  • @mickmackusa One of your skills is Putty? Really? Are you good at generating SSH keys? :D – Tpojka Nov 26 '17 at 00:09
0

In controller round the rating to 0.5

$rating = round($number*2)/2;

Pass the rating to the view and add this code:

    @for($x = 5; $x > 0; $x--)
    @php 
        if($rating > 0.5){
            echo '<i class="fas fa-star"></i>';
        }elseif($rating <= 0 ){
            echo '<i class="far fa-star"></i>';
        }else{
            echo '<i class="fas fa-star-half-alt"></i>';
        }
        $rating--;      
    @endphp
@endfor