2
Php

Laravel Tips – Generate Tablular Data With Actions

It’s a very common task in any web application to make a listing of models/records with actions related with them. Probably it’s not clear what I mean. Let’s see it below:

table

Hope it’s clear now. So, it’s a common task in any web application with a backend where an admin can add, edit or delete entries. Most often we need to do the same thing to generate a table like this and it’s realize it’s kind of annoying and repetitive so I was thinking if I could do this with any method call or helper function every time I need to generate something like this again and again. So, finally I’ve come up with a solution to automate this task a little bit. For example to generate the output that is given above as an image, all I need to do is:

In my controller (For Example)
$data = Ledger::paginate(10);
return View::make('ledgers.index')->with('data', $data);
In my view
@extends('layouts.master')

@section('content')
{{ 
	toTable($data->toArray()['data'], array(
		'attributes' => array('class' => 'table'),
		'only' => array('id', 'ladger_name', 'ladger_meta_date'),
		'action' => 'ledgers.action'
	))
}}

{{$data->links()}}
@stop

Here the $data is an instance of Illuminate\Pagination\Paginator and it could be a Collection object as well if I call get() instead of paginate(10) and in this case I need to change the code in my view as given below:

@extends('layouts.master')

@section('content')
{{ 
	toTable($data->toArray(), array(
		'attributes' => array('class' => 'table'),
		'only' => array('id', 'ladger_name', 'ladger_meta_date'),
		'action' => 'ledgers.action'
	))
}}

That’s it. I’ll get a table with records and action buttons associated with them very easily. So, what I did is that, I’ve just created a helper function named toTable and used it in my view. The function is given below:

// Generate Table with Action Buttons
function toTable($items, $options = null)
{
    $header = $atts = '';
    $header_keys = array_keys($items[0]);
    
    if(!is_null($options)) {
        if(array_key_exists('only', $options)) {
            $header_keys = $options['only'];
        }

        if(array_key_exists('attributes', $options)) {
            $attr = $options['attributes'];
        }
        else {
            $attr = array('class' => 'table table-condensed');
        }
    }
    else {
        $attr = array('class' => 'table table-condensed');
    }

    // Thead
    if(is_null($options) || (!isset($options['header']) || isset($options['header']) && $options['header'] != false)) {
        $header = "";
        foreach ($header_keys as $value) {
            $header .= "" . ucwords(str_replace('_', ' ', $value)) . "";
        }

        // If Actions attribute is available for action buttons add it in header
        if(isset($options['action'])) {
            $header .= "Actions";
        }
        $header .= "";
    }

    // Tbody
    $tbody = "";
    foreach ($items as $values) {
        $tbody .= "";
        foreach($header_keys as $key){
            $tbody .= "" . $values[$key] . "";
        }

        // If Actions attribute is available for action buttons then get it from another view
        if(isset($options['action'])) {
            $action = ''. View::make($options['action'], array('item' => $values)) . '';
            $tbody .= "$action";
        }
    }
    $tbody .= "";

    // Return only Tbody (if table == false)
    if(!is_null($options) && isset($options['table']) && $options['table'] == false) return $tbody;

    // Build attributes (id, class, style etc)
    if(isset($attr)) {
        foreach ($attr as $key => $value) {
            $atts .= " " . $key . "='" . $value . "'";
        }
    }
    
    // Return table with attributes (class, id, style etc)
    return "" . $header . $tbody . "
"; }

Probably I could have created a package or maybe I could have extended the Collection class but I think it’s not something so big for creating a package and a custom helper function is easy to integrate and modify if needed at any time. Anyways, so it helps me to easily generate tabular data with action buttons but for action buttons I’ve used separate views and in the function above, I’ve just used following code:

if(isset($options['actions'])) {
    $actions = ''. View::make($options['actions'], array('item' => $values)) . '';
    $tbody .= "$actions";
}

It’s obvious that I’ve used a separate Blade View for generating the action buttons and one that I’ve used for this example is as given below:

This view generates button groups and I can use a different set of buttons as well. So, anyways, lets look into the options that could be used with this function. The first parameter in the toTable function is an array of records and the second one is an array of options which is optional. So I can call the function like toTable($data->toArray()) and by default class='table table-condensed' is used to generate a Bootstrap-3 table and all the fields/columns will be dumped in the generated table. So, by providing some options I can customize the output and these are:

→ table (boolean) : Either true or false; for generating only a tbody without a parent table tag.
→ header (boolean) : Either true or false; for generating rows with or without header.
→ only (array) : For specifying the fields/columns to be available in the table.
→ attributes (array) : For using any attributes, i.e. class or id in the table tag.
→ action (string) : The name/path of the view file to be used to generate action buttons.

I’m keeping this function in a helper file in app/start/helpers.php file and including it in global.php file but it’s also possible to use a service provider to include the file. Probably there are other ways to minimize the task (generating a table with action buttons) but it helps me a lot to do it easily. Share your idea if you have something better than this. Thanks!

Latest Blog

0
Php

PHP – 8.0 Match Expression

In PHP 8.0 there is a new feature or I should say a new language construct (keyword) going to be introduced,  which has been implemented depending […]