I'm migrating a non-MVC application to Laravel 4.2 and I'm unsure of the best way to accomplish this task. I have several reports created on routes like this:
/reports/this_report
/reports/that_report
/reports/another_report
These actions query the database, run a bunch of calculations, and generate some html tables and forms.
What I need to add now is a page like this:
/reports/dashboard
This dashboard page should display the output of all 3 reports in a condensed format, each with a "click to view details" link that takes the user to the main report page.
Is there a way for the dashboard action to call each of the report actions, and use their output as data in the dashboard view?
Here's a little code of how you would do this. I'm not exactly sure how you have everything structured, so you might have to adapt this a little.
Lets say you have a route for the dashboard like this.
Route::get('/reports/dashboard', DashboardController#showDashboard');
This route should call a controller method that will do your processing.
class DashboardController extends BaseController
{
public function showDashboard()
{
return View::make('dashboard')->with(array(
'report1_data' => $this->getReport1Data(),
'report2_data' => $this->getReport2Data(),
'report3_data' => $this->getreport3Data()
));
}
public function getReport1Data() { //calculations, return array of results }
public function getReport2Data() { //calculations, return array of results }
public function getReport3Data() { //calculations, return array of results }
public function showThisReport()
{
$data = $this->getReport1Data();
return View::make('report')->with(array('data' => $data));
}
public function showThatReport()
{
$data = $this->getReport2Data();
return View::make('report')->with(array('data' => $data));
}
public function showAnotherReport()
{
$data = $this->getReport3Data();
return View::make('report')->with(array('data' => $data));
}
}
So, this dashboard method will call the other methods (that you will also include in this controller) that will query the database and calculate the reports.
Then it returns a View with all of the data. The view will format the data and display it to the user.
Now, to make it so you can see the detailed view of each report, I suggest adding a couple more methods and routes to show detailed views.
Route::get('/reports/this_report', 'DashboardController#showThisReport');
Route::get('/reports/that_report', 'DashboardController#showThatReport');
Route::get('/reports/another_report', 'DashboardController#showAnotherReport');
I hope this helps! Good luck.
Related
I am trying to get order data in order tab and profile details data in profile tab.
Is it possible to achieve ???
If Yes, then please tell me how ?
If No, then please tell me, laravel is the most advance framework of PHP, why we can't send multiple data from multiple methods in same View ?
Controller
public function GetOrders()
{
$gtord = DB::table('orders')->where('email',Session::get('email'))->get();
return view('/my-account')->with('gtord',$gtord);
}
public function ProfileEdit()
{
$data = DB::table('customers')->where('email',Session::get('email'))->first();
return view('/my-account')->with('data',$data);
}
Routes
Route::get('/my-account', 'App\Http\Controllers\CustomerController#ProfileEd');
Route::get('/my-account', 'App\Http\Controllers\CustomerController#GetOrders');
Thank you in advance
You can't have multiple routes with the same 'signature', ie method and url.
If you're just showing/hiding tabs using JS, what you can do is return the view with two variables, eg:
public function AccountView()
{
$data = DB::table('customers')->where('email',Session::get('email'))->first();
$gtord = DB::table('orders')->where('email',Session::get('email'))->get();
return view('/my-account')->with(['data' => $data, 'gtord' => $gtord]);
}
And then just use one route:
Route::get('/my-account', 'App\Http\Controllers\CustomerController#AccountView');
If the two tabs are different urls, or you're using Vue or similar you would have two distinct routes with different signatures.
First, you can't have 2 same routes with the same method. It's quite logical and necessary. Otherwise, the whole routing system would collapse.
On the other hand, you can have a function in the controller, and call the other functions to collect data.
// web.php
Route::get('/my-account', 'App\Http\Controllers\CustomerController#index');
// controller
public function index()
{
$orders = $this->getOrders();
$profile = $this->getProfiles();
return view('yourView', compact(['orders', 'profile']));
}
public function getOrders()
{
//
}
public function getProfiles()
{
//
}
BTW, it's a better practice to move custom function to models, services or traits, and keep only the functions of 7 verbs in the contoller.
I have model called Page and view called view.blade.php
//this is a model
public function Test()
{
return 'test';
}
//this is the template
<h1>{{$Test}}</h1>
how can I do this? please help me?
As I understood, you want to call model function inside your view? Do it like this:
{{Page::Test()}}
Edit:
If you need to use $this in your function to pass some data for your function (if that was what you were asking in comments below), you can do something like this. First define your static function:
public static function getPages()
{
return [
//some logic (get all pages)
];
}
Now, let's say this function will return multiple pages. If you want to filter them, and to display only one page on your view, you can pass the id of that view as a parameter to a next function which you will then pass to your view:
public function getSinglePage()
{
return self::getPages()[$this->id];
}
Lastly, in order to display the output of that function, use the same method as above, with new function name:
{{Page::getSinglePage()}}
I need to send the same result to almost every view page, so I need to bind the variables and return with every controller.
My sample code
public function index()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.index', compact('drcategory','locations'));
}
public function contact()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.contact', compact('drcategory','locations'));
}
But as you see, I need to write same code over and over again. How can I write it once and include it any function whenever I need?
I thought about using a constructor, but I cannot figure out how I can implement this.
You are able to achieve this by using the View::share() function within the AppServicerProvider:
App\Providers\AppServiceProvider.php:
public function __construct()
{
use View::Share('variableName', $variableValue );
}
Then, within your controller, you call your view as normal:
public function myTestAction()
{
return view('view.name.here');
}
Now you can call your variable within the view:
<p>{{ variableName }}</p>
You can read more in the docs.
There are a few ways to implement this.
You can go with a service, a provider or, like you said, within the constructor.
I am guessing you will share this between more parts of your code, not just this controller and for such, I would do a service with static calls if the code is that short and focused.
If you are absolutely sure it is only a special case for this controller then you can do:
class YourController
{
protected $drcategory;
public function __construct()
{
$this->drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
}
// Your other functions here
}
In the end, I would still put your query under a Service or Provider and pass that to the controller instead of having it directly there. Maybe something extra to explore? :)
For this, you can use View Composer Binding feature of laravel
add this is in boot function of AppServiceProvider
View::composer('*', function ($view) {
$view->with('drcategory', DoctorCategory::orderBy('speciality', 'asc')->get());
$view->with('locations', Location::get());
}); //please import class...
when you visit on every page you can access drcategory and location object every time
and no need to send drcategory and location form every controller to view.
Edit your controller method
public function index()
{
return view('visitor.index');
}
#Sunil mentioned way View Composer Binding is the best way to achieve this.
I have 2 separate partials views. I want to get the HTML with the given data from those partials views and have to send a Json response from controller.
Here is my code snippet.
public function myControllerFunction()
{
$response['products'] = view('search._partials.product_box')->with('data', $data['products]);
$response['filters'] = view('search._partials.facet_filters')->with('data', $data['filters]);
return $response;
}
I want to achieve some thing like it. This is possible with plain php code but is there any way to achieve it with this framework.
Just use render() function to generate html from view in controller
Your function should look like this
public function myControllerFunction()
{
$response['products'] = view('search._partials.product_box')->with('data', $data['products])->render();
$response['filters'] = view('search._partials.facet_filters')->with('data', $data['filters])->render();
return response()->json($response);
}
I'm returning data from Controller like this:
/**
* Password request sent
*
* #return array
*/
public function passwordRequestSentAction ()
{
return array(
'foo' => $this->bar,
);
}
But $this->foo is null within layout.phtml even though its correct within controller/passwordRequestSent.phtml
I had to create postDispatch method in my abstract controller and link to it in attachDefaultListeners() and do this in postDispatch:
$e->getViewModel()->setVariables($e->getResult()->getVariables());
Is that really the way to go? I simply want to share all my variables across, no matter if its layout or page template.
You can access the layout-template by calling $this->layout():
class MyController extends AbstractActionController
{
public function myAction()
{
$layout = $this->layout();
// Returns the ViewModel of the Layout
}
}
For more information & samples check the manual's examples.
However in most cases I'd suggest writing a viewhelper for these tasks - especially for navigation/... This encapsulates the controller's logic from viewing tasks like I want the navigation displayed here or Show me the user's login box. Same goes for almost every type of status messages.