How do I prevent repetition in my Laravel app? - php

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>{{ $product->name }}</td>
<td>{{ $product->sku }}</td>
<td>{{ Currency::display($product->price) }}</td>
<td>{{ $product->quantity }}</td>
<td>{{ Dates::showTimeAgo($product->created_at) }}</td>
<td>
Edit
{{ 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.

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 = '' . $product->name . '';
} 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>

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:

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

Related

Displaying Laravel foreach results

Below is my controller code.
foreach ($events as $eventId) {
$eventArray[] = Events::where('id', $eventId['event_id'])->get();
}
View
#foreach ($eventArray as $key => $value)
<tr>
<td>{{ $value }}</td>
</tr>
#endforeach
The result obtained is as follows.
[{"id":1,"event_title":"yoga","event_date":"2019-06-24 00:00:00"}]
How can I display the above results in a table?
You can change get to first as you are fetching event id wise data,
// first here to fetch one data
$eventArray[] = Events::where('id',$eventId['event_id'])->first();
Then in blade you can access with object syntax as ->
#foreach ($eventArray as $key => $value)
{{ dd($value)}}
<!-- or -->
{{ $value->id }}
#endforeach
Then you will know how to use it.
Recommended approach,
// fetch the required event ids
$eventIds = array_column($events, "event_id");
// then fetch the data for those ids
$eventArray = Events::whereIn('id', $eventIds)->get();
There is no need for that loop in your controller:
$events = Events::whereIn('id', array_column($events, 'event_id'))->get();
return $this->view('yourview', compact($events));
In your view:
<table>
<thead>
<tr>
<th>Title</th>
<th>Date</th>
</tr>
</thead>
<tbody>
#foreach ($events as $event)
<tr>
<td>{{$event->event_title}}</td>
<td>{{$event->event_date}}</td>
</tr>
#endforeach
</tbody>
</table>

PHP Laravel - Nested blade loop requiring SQL query

I am trying to return a loop to my blade template file with below result:
Main Name
Sub name #1
Sub name #2
Main Name
Sub name #1
Sub name #2
etc..
I have created a controller for this:
MergerController.php
public function index()
{
$MainOrganisations = DB::table('test')
->select('address', 'code', DB::raw('count(*) as amount'))
->where('code', 'LIKE', '64%')
->groupBy('address')
->orderBy('amount', 'desc')
->get();
foreach($MainOrganisations as $value){
$SubOrganisations = DB::table('test')
->select('name', 'code')
->where('address', $value->address)
->where('code', 'NOT LIKE', '64%')
->get();
}
$data = [
'MainOrganisations' => $MainOrganisations,
'SubOrganisations' => $SubOrganisations,
];
#Return data to our view
return view('merger.list')->with($data);
}
Then, inside my view file, I try to show this data:
list.blade.php
<table>
#foreach ($MainOrganisations as $Main)
<thead>
<th colspan="2">{{ $Main->address }}</th>
</thead>
<thead>
<th>Name</th>
<th>Code</th>
</thead>
<tbody>
#foreach($SubOrganisations as $Sub)
<tr>
<td>{{ $Sub->name }}</td>
</tr>
#endforeach
</tbody>
#endforeach
</table>
However, above only return the first result from $SubOrganisations, and then loops ONLY that result in my nested foreach:
#foreach($SubOrganisations as $Sub)
<tr>
<td>{{ $Sub->name }}</td>
</tr>
#endforeach
Returns:
Sub name #1
Sub name #1
Sub name #1
The way you are looping through each data for sub organization is wrong. Its better yo use eloquent relationship with eager loading for better performance.
Change your controller code:
public function index()
{
$MainOrganisations = DB::table('test')
->select('address', 'code', DB::raw('count(*) as amount'))
->where('code', 'LIKE', '64%')
->groupBy('address')
->orderBy('amount', 'desc')
->get();
foreach($MainOrganisations as $key => $MainOrganisation){
$SubOrganisations = DB::table('test')
->select('name', 'code')
->where('address', $MainOrganisation->address)
->where('code', 'NOT LIKE', '64%')
->get();
$MainOrganisation->subOrganisations = $SubOrganisations;
}
$data = [
'MainOrganisations' => $MainOrganisations
];
#Return data to our view
return view('merger.list')->with($data);
}
In you view:
<table>
#foreach ($MainOrganisations as $Main)
<thead>
<th colspan="2">{{ $Main->address }}</th>
</thead>
<thead>
<th>Name</th>
<th>Code</th>
</thead>
<tbody>
#foreach($Main->subOrganisations as $Sub)
<tr>
<td>{{ $Sub->name }}</td>
</tr>
#endforeach
</tbody>
#endforeach
</table>

Foreach to call values from one database table with different query in laravel

I want to retrieve values ​​from one database table but separated in two adjacent tables based on different id_produk (foreign key) values.
This is code in Controller :
public function index()
{
$item_ict = Item::where('id_produk', '1');
$item_cm = Item::where('id_produk', '2');
return view('item/index', compact('item_ict', 'item_cm'));
}
Then, I call $item_ict and $item_cm in index
<table class="table">
<thead>
<tr>
<th>ICT</th>
<th>CM</th>
</tr>
</thead>
<tbody>
#foreach ($item_ict as $itemict)
#foreach ($item_cm as $itemcm)
<tr>
<td>{{ $itemict -> nama_item }}</td>
<td>{{ $itemcm -> nama_item }}</td>
</tr>
#endforeach
#endforeach
</tbody>
</table>
is it the correct way when i wrote that foreach? Nothing errors, but no values exited. How the way to fix it?
Or i'm thinking about call it use query in index page, but i dont know how. is it possible? how?
Combine your items into one array so that you only need to do one loop.
Also, use ->get() to actually get the items. As it stands, your code is still just the query builder.
public function index()
{
$all = [];
$item_ict = Item::where('id_produk', '1')->get();
$item_cm = Item::where('id_produk', '2')->get();
for ($i = 0; $i < max($item_ict->count(), $item_cm->count()); $i++) {
$all[] = [
isset($item_ict[$i]) ? $item_ict[$i] : null,
isset($item_cm[$i]) ? $item_cm[$i] : null,
];
}
return view('item/index', compact('all'));
}
<table class="table">
<thead>
<tr>
<th>ICT</th>
<th>CM</th>
</tr>
</thead>
<tbody>
#foreach ($all as $items)
<tr>
<td>{{ $items[0] ? $items[0]->nama_item : null }}</td>
<td>{{ $items[1] ? $items[1]->nama_item : null }}</td>
</tr>
#endforeach
</tbody>
</table>

Laravel 5 Search Multi attribute Error

I`m new to the Laravel 5.4 .i needed to develop multiple attributed Search function.Here is the error um getting .
Here is my registered.index.blade.php View
<div class="panel panel-default">
<div class="panel-body">
<table class="table table-striped">
<thead>
<th>Full Name</th>
<th>Name with initials</th>
<th>National ID Number</th>
<th>Date Of Birth</th>
</thead>
<tbody>
#foreach($items as $item)
<tr>
<td>{{ $item->full_name }}</td>
<td>{{ $item->name_with_initials }}</td>
<td>{{ $item->nic_no }}</td>
<td>{{ $item->date_of_birth }}</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
Here is the my Controller .
public function search_code(Request $request){
$query = $request->search;
$queryType = $request->institute; // 'id' or 'name'
$items = DB::table('registerdetails');
if($queryType == 'id'){
$items = $items->where('id', 'LIKE',"%$query%");
}
if($queryType == 'name'){
$items = $items->where('name', 'LIKE',"%$query%");
}
$items->get();
return view('registeredusers.index')->with('items',$items);
}
Can Anyone suggest me the solution for this error?
Change this:
$items->get();
To this:
$items = $items->get();
When you're doing just $items->get();, the $items variable has an instance of Query Builder and not query result.

Select List From Database With Parameter

Hi there i have some problem getting list from database using laravel 4.1
I have session that stored some value about companyid. Then i want to print the list to table based on the companyid itself. Let say i can access the session using {{ Session::get('name')}}
This is my controller index()
public function index($cid) {
$pengguna = User::where('id_company', '=', $cid)->get();
$pengguna->toarray();
$data = array(
'pengguna' => $pengguna,
'page' => 'master',
'index' => 0
);
return View::make('console.pengguna')->with($data);
}
then i want to print the data to table in view
#if($pengguna->count())
<table class="table table-striped table-bordered" id="table_pengguna_list">
<thead>
<tr>
<th>No</th>
<th>Firstname</th>
<th>Lastname</th>
<th>Username</th>
<th>Email</th>
<th>Status</th>
<th>Last Login</th>
<th class="td-actions">Action</th>
</tr>
</thead>
<tbody>
#foreach ($pengguna as $pgn)
<tr>
<td>{{ $index++ }}</td>
<td>{{ $pgn->firstname }}</td>
<td>{{ $pgn->lastname }}</td>
<td>{{ $pgn->username }}</td>
<td>{{ $pgn->email }}</td>
<td>{{ $pgn->level }}</td>
<td>{{ $pgn->updated_at }}</td>
</tr>
#endforeach
</tbody>
</table>
....
how to pass the parameter from session to the controller then? so basically pass the {{ Session::get('name')}} to $cid in index controller.
thank you.
hi there i have found the solution, just place refactor the index controller to;
public function index() {
$cid = Session::get('name');
$pengguna = User::where('id_company', '=', $cid)->get();
$pengguna->toarray();
$data = array(
'pengguna' => $pengguna,
'page' => 'master',
'index' => 0
);
return View::make('console.pengguna')->with($data);
}

Categories