Reputation: 729
I am currently working on a new large app and I am trying to ensure I implement best practices from the start. I am new to Laravel so one question I have is how can I limit repetition throughout my app.
As an example I currently have a resource controller for an admin section that makes a view like so:
public function index()
{
// $data will be passed to the view
$data = array(
'pageTitle' => 'Manage Products',
'btn' => array(
'title' => 'Add product',
'url' => 'admin.catalog.product.create',
)
);
return View::make('catalog::product.index', $data)->with('products', Product::all());
}
My view file looks likes so:
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>SKU</th>
<th>Price</th>
<th>Qty</th>
<th>Created</th>
<th><i class="icon-cog"></i></th>
</tr>
</thead>
<tbody>
@foreach ($products as $product)
<tr>
<td>{{ $product->pid }}</td>
<td><a href="{{ URL::route('admin.catalog.product.edit', $product->pid) }}">{{ $product->name }}</a></td>
<td>{{ $product->sku }}</td>
<td>{{ Currency::display($product->price) }}</td>
<td>{{ $product->quantity }}</td>
<td>{{ Dates::showTimeAgo($product->created_at) }}</td>
<td>
<a href="{{ URL::route('admin.catalog.product.edit', $product->pid) }}" class="btn btn-success btn-mini pull-left">Edit</a>
{{ Form::open(array('route' => array('admin.catalog.product.destroy', $product->pid), 'method' => 'delete', 'data-confirm' => 'Are you sure?')) }}
<button type="submit" href="{{ URL::route('admin.catalog.product.destroy', $product->pid) }}" class="btn btn-danger btn-mini">Delete</button>
{{ Form::close() }}
</td>
</tr>
@endforeach
</tbody>
Is there a way that I can just use the one view file for all admin tables and pass what columns I want for the header and body through the controller instead of hard coding this in the view like above?
I know I can pass the $data array but not sure how to go about passing the columns I want through this. Any ideas or suggestions would be much appreciated.
Upvotes: 1
Views: 921
Reputation: 729
Thanks for all the responses. I actually ended up using a package created by Rob Gordijn. Works great for me and prevents a lot of repetition. You can get this package at the URl below:
https://github.com/RobGordijn/Bamboo
Upvotes: 0
Reputation: 146191
I would like this
View:
<table>
<thead>
<tr>
@foreach ($records[0] as $k => $v)
<th>{{ ucwords(str_replace('_', ' ', $k)) }}</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach ($records as $record)
<tr>
@foreach ($record as $col)
<td>{{ $col }}</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
Controller: (Using getColumns
helper function)
$users = User::all();
// In the first array, just pass the fields
// you want to get, second one is data array
$data['records'] = getColumns(array('id', 'username', 'email'), $users->toArray());
return View::make('user.users', $data);
Or, you may use it like this
$users = User::all()->toArray();
// In this example, I want to show only
// username, first_name and last_name
$records = getColumns(array('username', 'first_name', 'last_name'), $users);
return View::make('user.users')->with('records', $records);
This is a helper function, it's possible to use this from any model/controller
function getColumns($keys, $result)
{
$records = array();
foreach ($result as $row) {
$record = array();
foreach ($row as $k => $v) {
if(in_array($k, $keys)) $record[$k] = $v;
}
$records[] = $record;
}
return $records;
}
I'm using helper function because, I can use it with any model and it's in my filters.php
file, you can put it anywhere. Actually, I have a file custom_helpers.php
file in app
folder where filters.php
and at the end of my filters.php
file, I've this
include "custom_helpers.php";
In this custom_helpers.php
I've this helper function with other functions. Here is an example with screenshot
$users = User::take(5)->get()->toArray();
$records = getColumns(array('username', 'first_name', 'last_name'), $users);
return View::make('user.users')->with('records', $records);
Screen Shot:
Upvotes: 1
Reputation: 346
I don't think this really is a question regarding Laravel, but hey, here we go.
You could add functions to your models to map column names to your values.
public function getColumns()
{
return array(
'ID' => 'pid',
'Name' => 'name',
....
);
}
public function getColumnData()
{
$columns = $this->getColumns();
$records = [];
foreach ($columns as $column) {
if ('name' == $column) {
$data = '<a href="' . URL::route('admin.catalog.product.edit', $this->pid) . '">' . $product->name . '</a>';
} if else (..) {
...
} else {
$data = $this->{$column};
}
}
return $records;
}
And your view would become something like this:
<thead>
<tr>
@foreach ($records->first()->getColumns() as $column)
<th>{{ $column->name }}</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach ($records->all() as $record)
<tr>
@foreach ($record->getColumnData() as $data)
<td>{{ $data }}</td>
@endforeach
</tr>
@endforeach
</tbody>
Upvotes: 3