How to call a controller from within a view - Laravel - laravel

I have a view that lists timesheets.
on that view, each timesheet has a deliverable field... I have a DeliverableController that has an action "DropdownList" that calls upon the model and gets a list of deliverables and pushes them to a deliverable view (which just creates a dropdown box).
When im looping through my timesheets I would like to get the response of the DeliverableController/DropdownList and put it where my deliverable field should be on the timesheet.
A) is there a way of getting the response of a controller from within a view
B) is there a way of getting the response of a controller from within a controller method, so that I can push the result to the view?
My code so far is:
DeliverableController:
class DeliverableController extends BaseController {
private $deliverableRepository;
function __Construct( IDeliverableRepository $deliverableRepo )
{
$this->deliverableRepository = $deliverableRepo;
}
...
public /* */ function DropdownList()
{
$deliverables = $this->deliverableRepository->Deliverables();
return View::make( 'Deliverable/_DropdownList', array( "Model" => $deliverables ) );
}
}
Deliverables/_DropdownList View:
<?php
foreach( $Model as $item )
{
?>
<select name="">
<option value = "<?php echo $item->ID; ?>"><?php echo $item->Title; ?></option>
</select>
<?php
}
?>
Timesheet Controller:
class TimesheetController extends BaseController {
private $timesheetRepository;
function __Construct( ITimesheetRepository $timesheetRepo )
{
$this->timesheetRepository = $timesheetRepo;
}
...
// [HttpGET]
public /* */ function GetCreate()
{
return View::make( 'Timesheet/Create' );
}
// [HttpPOST]
public /* */ function PostCreate()
{
// To do
}
}
Timesheet/Create
#extends( 'layout' )
#section( 'Styles' )
<link href="<?php echo Request::root(); ?>/Styles/Timesheet.css" rel="stylesheet">
#stop
#section( 'Title' )
Create timesheets
#stop
#section( 'Content' )
<form role="form">
<table id="TimesheetTable" class="table">
<thead>
<tr>
<th>Project/Deliverable</th>
...
</tr>
</thead>
<tfoot>
<tr>
<td></td>
...
</tr>
</tfoot>
<tbody>
<?php
for( $a = 0; $a < 18; $a++ )
{
?>
<tr id='row<?php echo $a; ?>'>
<td><?php /* Get response from DeliverableController/DropdownList */ ?></td>...
</tr>
<?php
}
?>
</tbody>
</table>
#stop
#section( 'Scripts' )
<script src="<?php echo Request::root(); ?>/Scripts/Timesheet.js"></script>
#stop
Notice the /* Get response from DeliverableController/DropdownList */

If you would like to call a controller from a view you can use the IOC container
App::make(//ControllerName)->//methodName(//parameters);
Example:
App::make("UserController")->displayUsers(array('page_id' => 55));

This far from ideal, but a controller is a class as any other one, so you might be able to:
with(new UsersController)->doWhatever();
But if you are in need of doing something like that looks like your controllers are not really following some design patterns and they might have too much resposibilities, just to enlist some:
1 - A controller should not know much about your business logic. Controllers should receive a request send them to a model (or a repository) the the processed data and provide this data to a view or just redirect the user to another route.
2 - A controller should not be called by any other piece of code than the router itself.
3 - A view should not be aware of your classes and process things, they should receive data (already processed) from controllers and show them.
4 - The single responsibility principle that one should be responsible for doing just one. If your are calling a controller from your view, your view is being responsible for showing AND processing, and your controller is having the responsibility of a normal class (or a model or a repository) and also a controller.
And just with what you've said this list could go on...
What Laravel developers would basically tell you to do:
1 - Create a controller that does almost nothing:
class WhateverController extends Controller {
private $repository;
public function __construct(RepositoryInterface $repository)
{
$this->repository = $repository;
}
public function whatever()
{
$data = $this->repository->processData(Input::all());
return View::make('your.view')->with(compact($data));
}
}
2 - And everything that you need to do to generate data to your view you do in your repository class. You can have other classes instantiated (or inject) inside your repository to do whatever you need to do:
class Repository implements RepositoryInterface {
public function processData($input)
{
$dataProcessor = new DataProcessor;
return $dataProcessor->process($data);
}
}

i think is better for you to create Class Aliases.
open app/config/app.php
add field on array aliases
example :
UserSession => App\Libraries\UserSession
and you can call it on your view simply
example :
UserSession::getData()

Related

I try to show variable from the controller to blade in laravel but the result is "Undefined Variable"

I try to show variable from the controller to blade in laravel but the result is "Undefined Variable $bedrijven , i tried to not use as bedrijf but with no avail
enter image description here"
The controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Bedrijf;
class Bedrijven extends Controller
{
//
function viewLoad()
{
return Bedrijf::all();
return view ('list',['Bedrijven'=>$data]);
}
}
//
{
//
function account (Request $req)
{
return $req->input();
}
}
The blade file
<html>
<table>
<tr>
<td>Id</td>
<td>bedrijven_id</td>
<td>Body</td>
</tr>
#foreach($bedrijven as $bedrijf)
<tr>
<td>{{$bedrijf['id']}}</td>
<td>{{$bedrijf['bedrijven_id']}}</td>
<td>{{$bedrijf['body']}}</td>
</tr>
#endforeach
</table>
</body>
</html>
</div>
</body>
</html>
the route
Route::get('list', [Bedrijven::class, 'show']);
in your controller there is not a $data variable that's why it shows a error
to fix it try this:
function viewLoad()
{
$data = Bedrijf::all();
return view ('list',['Bedrijven'=>$data]);
}
instead of :
function viewLoad()
{
return Bedrijf::all();
return view ('list',['Bedrijven'=>$data]);
}
Minor spelling mistake and the methods controller does not match the route definition. It is quite easy to use compact, to create the array for the view data.
public function show() {
$bedrijven = Bedrijf::all();
return view ('list', compact('bedrijven'));
}
Now the blade code will match the compacted data.
#foreach($bedrijven as $bedrijf)

Differentiate two views with buttons

I have a view in which I display two data that I take from a table of a DB and next to these data I have two buttons that take me to the same view in which I need to display other things.
What I can't figure out is, how do I differentiate the view AFTER pressing the button?
Here there are the images of the two view:
https://imgur.com/a/i5BcPaw
The code is the following:
Controller:
<?php
namespace App\Http\Controllers;
use App\Models\Device;
use App\Models\DataFromRasp;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
class DeviceController extends Controller
{
public function index()
{
$data=Device::all();
return view('backend.auth.user.device', compact("data"));
}
public function create()
{
}
public function store(Request $request)
{
}
public function show(Device $deviceID)
{
}
public function edit(Device $device)
{
//
}
public function update(Request $request, Device $device)
{
//
}
public function destroy(Device $device)
{
//
}
/**
* Displays all data present in the table data_from_rasps
*
* The data are all the devices that the raspberry can capture
*/
public function visualizeData()
{
$data=DataFromRasp::paginate(10);
return view('backend.auth.user.dictionary', compact("data"));
}
/**
* Raspberry capture and send the data to the DB and save in another
* table of the same DB the MAC addresses of interest
*/
public function getData(Request $request)
{
$m_data = $request->get('m_data');
$r_data = $request->get('r_data');
DataFromRasp::create(['MAC' => $m_data, 'RSSI' => $r_data]);
if(($m_data == 'C4:A5:DF:24:05:7E') and Device::where('MAC_ADDR', $request->m_data)->doesntExist()){
Device::create(['USERNAME'=>'Device1','MAC_ADDR' => $m_data]);
}
if(($m_data == '70:1C:E7:E4:71:DA') and Device::where('MAC_ADDR', $request->m_data)->doesntExist()){
Device::create(['USERNAME' => 'Device2','MAC_ADDR' => $m_data]);
}
}
public function scan()
{
$process = new Process(['C:\Simone\Università\Tirocinio\laravel-boilerplate-master', 'prova.py']);
$process->run();
if (!$process->isSuccessful()) { throw new ProcessFailedException($process); }
return redirect()->route('dict');
}
public function singleDev(Device $deviceID){
$data = DataFromRasp::select('RSSI', 'created_at')->where('MAC', 'C4:A5:DF:24:05:7E')->get();
$time_array = [];
$rssi_array = [];
$cnt = 0;
foreach($data as $dataItem){
array_push($time_array, $dataItem->created_at->format('H:i:s'));
array_push($rssi_array, $dataItem->RSSI);
}
return view('backend.auth.user.singleDevice', compact("time_array", "rssi_array"));
}
}
View where I select the device:
#extends('backend.layouts.app')
#section('content')
<table class="table">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">USERNAME</th>
<th scope="col">MAC ADDRESS</th>
</tr>
</thead>
<tbody>
#foreach ($data as $item)
<tr>
<th scope="row">{{$item->id}}</th>
<td>{{$item->USERNAME}}</td>
<td>{{$item->MAC_ADDR}}</td>
<td>
Select
</td>
</tr>
#endforeach
</tbody>
</table>
#endsection
Does anyone know how to do this?
Thanks in advance
Try to use this code
Select
Instead of
Select
Updated!
I a little bit didn't get what you trying to achieve, but why didnt your try to add another button next to it, to show another view?
You could create an if statement to determine if one of the buttons is pressed whenever you load the page.
In blade
<button type="submit" name="device_id" value="$item->id">Select</button>
In controller
$data=Device::all();
$singleDevice = Device::where('id', '=', Input::get('device_id'))->first();
if($singleDevice === null)
{
return view('backend.auth.user.device', compact("data"));
}
else
{
$time_array = [];
$rssi_array = [];
$cnt = 0;
foreach($singleDevice as $dataItem){
array_push($time_array, $dataItem->created_at->format('H:i:s'));
array_push($rssi_array, $dataItem->RSSI);
}
return view('backend.auth.user.singleDevice', compact("time_array", "rssi_array"));
}

get the Id from a item grid and save into a variable

I'm working with Laravel 5 to do the following: I have a grid that shows all the clients that the company has, in each row of that grid, there is a button to select that client like this:
Grid of clients
This button sends me to a separate screen that is related directly with the selected client, when this happens, the URL is as follows:
http://sistemaprueba.com/modulos?1
where the value after the question mark represents the value of the id of the selected client. Now, I need to save the value of that id in a variable to be able to use it later, how can I do that?
This is my grid:
<div class="row">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Nombre Cliente</th>
<th>Ingresar</th>
</tr>
</thead>
<tbody>
#foreach($results as $result)
<tr>
<td>{{$result->nombre_cliente}}</td>
<td></i>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
This is the route to the new screem:
Route::get('/modulos', 'HomeController#modulos')->name('modulos');
and my controller looks like this:
class ClientController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$id = \Auth::user()->id;
$results = DB::table('clients')->join('clients_company', 'clients_company.fk_id_client', '=', 'client.id')
->where('clients_company.fk_id_usuar',$id)->get();
return view('clients',compact('results'));
}
public function modulos()
{
return view('modulos');
}
}
You could either change your href to "/modulos/1" and your route and controller to:
// route
Route::get('/modulos/{clientId}', 'HomeController#modulos')->name('modulos');
// controller
public function index($clientId)
{
// Use $clientId
}
Or give a named parameter in your url, like "/modulos?clientId=1", then:
// route (unchanged)
Route::get('/modulos', 'HomeController#modulos')->name('modulos');
// controller
public function index()
{
$clientId = request()->input('clientId');
...
}
Alternatively, you could parse the url with PHP's function parse_url() in your controller, to extract the GET part of the url for you to manipulate. Not the cleanest solution. http://php.net/manual/en/function.parse-url.php
The first method may be preferable for your purpose.

trying to return a view from database but getting -"Undefined variable error - Laravel 5.2"

Controller,Route and view code is below.
Getting error
trying to return a view from database but getting -"Undefined variable error - Laravel 5.2"
Football.blade.php
#if (isset($football_datas))
#foreach($football_datas as $football_data)
{{$football_data->day}}
</h3>
<div style="height:20px;">
<p class="time-identity" > 14:00</p>
<a href="{{Route('stream')}}" >
<p class="match-identity">{{$football_data->country}} vs {{$football_data->country}}</p>
<p class="live-video-identity"> video </P>
</a>
</div>
#endforeach
#endif
football_dataController.php
class football_datacontroller extends controller
{
public function index(){
$football_datas= DB::table('football_datas')->select('id','country','day')->get();
return view('football',['football_datas'=>$football_datas]);
}
}
routes
Route::post('football', 'football_dataController#index');
Can you try this on your Controller.
return view('football',compact('football_datas'));
Your code
return view('football',['football_datas'=>$football_datas]);
Try
return View::make('football')->with('football_datas', $football_datas);
I hope it helps.
You can use this way for variables, so you wont need to do all them custon changes:
class football_datacontroller extends controller
{
public function index(){
$football_datas= DB::table('football_datas')->select('id','country','day')->get();
$vars['football_datas'] = $football_datas;
return view('football', $vars);
}
}
Then, you can add several "$vars['blabla]' = $blabla" on top of eachother, and all variables will be available in the view with just the {{$football_datas}} or {{$blabla}} in the examples provided.
Example here under on how to have several:
class football_datacontroller extends controller
{
public function index(){
$football_datas= DB::table('football_datas')->select('id','country','day')->get();
$vars['blabla'] = $blabla;
$vars['football_datas'] = $football_datas;
return view('football', $vars);
}
}

Laravel:Dont show error if relation dont exist

I have controller and i am getting data like this
$events= Eventm::with('teacher')->get();
Every event has one teacher then in view i am taking data like
$event['teacher']->name
its work fine if their their is relation between teacher and events. but if their is no teacher in teacher column (or Admin delete the teacher but still event contain the teacher id). the view don't render at all and show error trying to get property of non object. I want that if teacher data is deleted the view will not throw error , just show no text on
$event['teacher']->name
is it possible ?
You can do in your view
#if($event['teacher'])
<div class="whatever">$event['teacher']->name</div>
#else
<div class="whatever">Teacher not found.</div>
#endif
Another possibility is to do what you should be doing anyway: pass from controller the data to be displayed in the view. Your view should not be complicated and it should not be aware of your objects and your data, you should pass to it the data it is supposed to display. This is somethig you should be doing in a presenter or just in another class:
<?php
class ProcessEventsViewData {
private $events;
public function __construct($events)
{
$this->processData($events);
}
public function processData($data)
{
foreach($data as $event)
{
$this->processEvent($event);
}
}
public function processEvent($event)
{
$this->events[$event->id]['name'] = $event->name ?: 'Event name not found';
$this->events[$event->id]['teacher'] = $event->teacher ? $event->teacher->toArray() : array('name', 'Teacher not found');
}
public function getData()
{
return $this->events;
}
}
class MyController extends Controller {
$events = Eventm::with('teacher')->get();
$eventData = new ProcessEventsViewData($events);
return View::make('event')->with('events', $eventData->getData());
}
And in your view you now can just:
#foreach($events as $id => $event)
Event ID: {{$id}};
Event Name: {{$event['name']}};
Teacher: {{$event['teacher']['name']}};
#endforeach

Resources