Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

[Proposal] Add current index in Blade template loops #420

Closed
tommymarshall opened this Issue Feb 24, 2013 · 22 comments

Comments

Projects
None yet

I find myself pretty often adding $i = 0; above my @foreach loops then incrementing on each iteration. It would be nice if we could reference {{ index }} to return the current step of where we're at in the loop. It seems appropriate for a templating language. I understand this may open the door to other arbitrary indexing methods like {{ first }} and {{ last }}, in which case using https://packagist.org/packages/smarty/smarty may be a better choice anyways.

Contributor

bencorlett commented Feb 24, 2013

Sweet idea! Though, I'm not sure that's within the scope of how Blade was written to be honest.

Blade, when it compiles, simply replaces your openings, such as foreach with the PHP equivilent, e.g., @foreach ($foo as $bar) is simply preg_replace'd to be <?php foreach ($foo as $bar): ?>.

There's no object holding each iteration of the loop in the context of compilation, unfortunately :(. If you want that, I'd be jumping ship to a full templating engine such as, as you said, smarty, or twig or something. You can easily integrate these with L4.

Contributor

robclancy commented Feb 25, 2013

I highly doubt this will happen. Blade is a simple templating language which basically just makes stuff you use in PHP shorter.

To get your index like you want with {{ index }} you just do {{ key($theArrayYouAreLoopingThrough) }}.

Owner

taylorotwell commented Feb 25, 2013

As @bencorlett noted, this would be quite difficult to do in Blade. Going to defer it for now.

Contributor

franzliedke commented Oct 27, 2013

I know this is old, but just for reference, why not just use @foreach ($array as $index => $value)?

Contributor

robclancy commented Oct 27, 2013

Hahaha so true.

@franzliedke, @robclancy : That wouldn't work with an associative array like "loop" does in twig. loop always returns the numeric index even in an associative array, whereas key() or foreach will actually return the name of the key.

Contributor

robclancy commented Jul 18, 2014

Welcome to PHP.

Useful workaround example while wait for solution

/* UsersController */
$data = [

    'users' => [  

          [
              'name' => 'Juninho',
              'family' => 'De Luca',
          ],
          [  
              'name' => 'Homer',
              'family' => 'Simpson',
          ],
          [  
              'name' => 'Bart',
              'family' => 'Simpson',
          ],
     ],

    'i' => 0,
];

return view('users.index', $data);


/* users/index.php */
@foreach ($users as $user)
    {{ $i ++ }}
@endforeach

renege commented Jul 28, 2015

@juninhodeluca
wy2av4yajsdxs

lol like I said: workaround ;)

Contributor

kirkbushell commented Aug 18, 2015

@juninhodeluca a better workaround is simply put it in the view. It's view logic, afterall.

You can do it this way:

@foreach ($collection as $index => $element)
    {{$index}} - {{$element['name']}}
@endforeach

Source: http://stackoverflow.com/a/24149137/2049990

Contributor

DCzajkowski commented Jan 24, 2016

Solution

For anyone waiting for a solution, implement this in your AppServiceProvider:

<?php

namespace Stori\Providers;

use Auth;
use Blade;
use Hash;
use Illuminate\Support\ServiceProvider;
use Validator;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        /**
         * Does not support nesting
         */
        Blade::directive('index', function($expression) {
            return '<?php echo $index; ?>';
        });
        Blade::directive('foreachIndexed', function($expression) {
            return '<?php $index = 1; foreach' . $expression . ': ?>';
        });
        Blade::directive('endforeachIndexed', function($expression) {
            return '<?php $index++; endforeach; ?>';
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

Usage

@foreachIndexed($array as $key)
    @index
@endforeachIndexed

Solution #2

@foreach ($fields as $field)
    {{ array_search($field, array_keys($fields)) + 1 }}
@endforeach
Contributor

franzliedke commented Jan 25, 2016

@czajekdc That will break once you nest these loops, though.

Contributor

DCzajkowski commented Jan 25, 2016

Yeah, you are right.
In a doc block should be "Do not nest!". Haha

Contributor

DCzajkowski commented Jan 25, 2016

EDIT: Updated the code with Solution #2. Added a DocBlock.

I am creating Blade directive in my service provider

\Blade::directive('var', function($expression) {
    $regex = "/\((['\"])([\w_]+)\\1,\s*([^\)]+)\)/";
    return preg_replace($regex, '<?php $$2 = $3; ?>', $expression);
 });

Then you can easily use it in your views

@var('i', 0)
@foreach (...)
    {{{ $i++ }}}
@endforeach

Sorry for bringing this once again, but thought it either could be useful for someone or someone will prove me why this is bad

This also works but looks very ugly:

{{{ '' != $i = 0 }}}
@foreach (...)
    {{{ $i++ }}}
@endforeach

I find something like this to work (laravel 5.2), unless that isn't what the op is looking for
@foreach($something as $key=>$value)
{{ $key }} then {{ $value }}
@endforeach

where the $something is something like this:

[{
  "id": 1,
  "foo_id": "1",
  "title": "Duh",
}]
Contributor

kirkbushell commented Aug 7, 2016

It's been closed - it's already coming in 5.3 I believe.

luqmanrom commented Sep 8, 2017 edited

Old thread but just to add it here as a reference for someone who found this post and looking for the answer as I did. This is now implemented in Laravel 5.3

The index can be accessed by using $loop variable.

Refer: https://laravel.com/docs/5.3/blade#the-loop-variable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment