Is it possible to execute multiple functions in the same controller with one route. I thought it would be something like this but it doesn't work.
Route::get('getdata','controller#getData', 'controller#getData1', 'controller#getData2');
In the controller are these functions:
getData
getData1
getData2
Or is there a easier way?
In the controller
Add something like this.
class YourController extends Controller {
//...
protected function getAllData() {
//Executes the seperate functions.
$this->getData();
$this->getData1();
$this->getData2();
}
//...
}
This will execute the functions respectively.
Then from your route, you just call YourController#getAllData as the function of the controller.
It does not make sense if multiple controller actions are responsible for a single route. That's not how MVC works. You should have one and only one action for each route, and call every other function you need inside that action.
And remember, for best practices each method of the controllers must contain only the code to respond the request, not business logic, and if you have any other functions which needs to be called, put them in another other classes (layers).
class MyController extends Controller {
public function myAction(MyService $myService) {
$myService->getData();
// not $this->getData()
}
}
Related
I have been declaring all the routes for my application inside web.php , but it is now getting quite large. I find that I am losing a lot of time shifting between web.php and each controller and this is hurting productivity.
I feel like it would be better to define routes inside of the controller, perhaps ideally delegating some URL to a controller and then allowing the controller to handle the "sub routes" since this would allow me to use inheritance when I have two similar controllers with similar routes.
It is not possible given how laravel works. Every request is passed onto router to find its designated spot viz. the controller with the method. If it fails to find the route within the router, it just throws the exception. So the request never reaches any controller if the route is not found. It was possible in earlier versions on Symphony where you would configure the route in the comment of a particular controller method.
Sadly with laravel it works how it works.
But for me, I just like to have the routes in a separate file.
Alternate solution, easier way to sort all the routes.
You can move your route registration into controllers if you use static methods for this. The code below is checked in Laravel 7
In web.php
use App\Http\Controllers\MyController;
.....
MyController::registerRoutes('myprefix');
In MyController.php
(I use here additional static methods from the ancestor controller also posted below)
use Illuminate\Support\Facades\Route;
.....
class MyController extends Controller {
......
static public function registerRoutes($prefix)
{
Route::group(['prefix' => $prefix], function () {
Route::any("/foo/{$id}", self::selfRouteName("fooAction"));
Route::resource($prefix, self::selfQualifiedPath());
}
public function fooAction($id)
{
........
}
In Controller.php
class Controller extends BaseController {
....
protected static function selfAction($actionName, $parameters = [], $absolute = false)
{
return action([static::class, $actionName], $parameters, $absolute);
}
protected static function selfQualifiedPath()
{
return "\\".static::class;
}
protected static function selfRouteName($actionName)
{
//classic string syntax return "\\".static::class."#".$actionName;
// using tuple syntax for clarity
return [static::class, $actionName];
}
}
selfAction mentioned here is not related to your question, but mentioned just because it allows making correct urls for actions either by controller itself or any class using it. This approach helps making action-related activity closer to the controller and avoiding manual url-making. I even prefer making specific functions per action, so for example for fooAction
static public function fooActionUrl($id)
{
return self::selfAction('foo', ['id' => $id]);
}
Passing prefix into registerRoutes makes controller even portable in a sense, so allows inserting it into another site with a different prefix in case of conflict
I have a controller with the "getUsers" function in a controller called "UserController" , and inside it I want to call a function of the "CarController" controller called "getCars", the two options I have are:
a) Make the second call as "static" , then I can call it without instantiating the class
b) Do not do that function of the static class and I call it in this way
$ car_id = 100;
$ userController = new UserController ();
$ userController-> getCars ($ car_id);
I do not know which is the best practice, or what pros or cons has one or another.
I'm using laravel.
Thanxs.
It is a bad practice to call a controller from another controller, this usually signals that you have badly designed your code and you should think of a different way to achieve what you want.
None the less, you can do it like this:
app()->call('App\Http\Controllers\CarController#getCars');
If your controller method has parameters you can pass them as the second argument:
app()->call('App\Http\Controllers\CarController#getCars', [$param1, $param2]);
To answer your question, you should not call one controller method from another. As #elfu mentioned, this is not the intended functionality of a controller anyway. His post is correct and in your case you should probably use the User model as the location of this method, but I thought I'd at to it a little.
If you do want to share methods between multiple controllers, a good place to do this is through a Trait. In some cases, you are not referencing a model that is shared between controllers, and a Trait would be your best option.
To include a trait, you can reference it by including it at the top of your controller and then with a 'use' statement after the class declaration for the controller. Here is an example:
use App\Traits\ExampleTrait;
class CarController extends Controller
{
use ExampleTrait;
...
You would do the same in the UserController. Then, any method that you place in the ExampleTrait will be directly accessible from the CarController and the UserController by referencing it as $this->methodName(), just like referencing any other method in the same controller.
In your particular case, I would say that your logic should probably be stored in the User model, since the cars for a user are really an ATTRIBUTE of the User model, but the above gives you another option to work with.
In my humble opinion you should not call another controller in a controller.
It looks like you have some business logic in that controller. So you should move your logic to the entity (User.php) and call it in both controllers methods.
A regular controller returns a view (at least that is what is expected), so if you want to call another controller you should just send that route to that method (in web.php file) instead of calling it in another controller.
Hope that helps you.
You can call one controller function from another but the best way is to create a trait and use it both the controllers like:
trait Common
{
public function method(){}
}
class FirstController extends Controller
{
use Common;
}
class SecondController extends Controller
{
use Common;
}
If you want to bind parameters to the call, you can use:
$videos = app()->call('App\Http\Controllers\StorageController#returnViewVideo',[
'course'=>$course,
'lesson'=>$lesson,
]);
The following code worked for me well. and also it also can be used in routes.php
public function mobileImageUpload(Request $request){
$this->validate($request,[
'data'=>'required',
'filetype'=>'required',
'userid'=>'required',
]);
$namespace = 'App\Http\Controllers';
$controller = app()->make($namespace.'\ImageController');
return $controller->callAction('mobileImageUpload',[$request]);
}
What I wanna do is to know, inside a view, if I'm in a specific controller or not. From what I know, I've got two choices and I don't have the answer to either of them :-D
inject a view variable using the share method in my AppServiceProvider, which involves getting the current controller name(or at least the action name so that I can switch it) inside the service provider.
inject a variable to all the views returned in the controller. For example does controllers have a boot method? Or can I override the view() method in the following code snippet?
public function someAction(Request $request)
{
return view('someview', ['myvar' => $myvalue]);
}
well of course there's the easy (yet not easy :|) solution: add the variable in all methods of the controller. I don't like this one.
Thanks
You could use the controller's construct function.
Add this to the top of your controller:
public function __construct()
{
view()->share('key', 'value');
}
I Need some advice, as I'm still a bit new to Laravel and MVC in general. I'm coding a small web application that presents some data on the page, fetched from a remote API. However, the page already has a controller to it. The other controller I will be using I'm hoping I can also reuse it for other pages. I'm pretty stuck here.
So the two controllers
HomeController.php
ApiController.php
The HomeController is the original controller, which gets the view file (home.blade.php), with some other data that's being loaded from the controller.
With the ApiController, I want to fetch the api (json) results, do some changes and then load those changes to the HomeController as well. The changes would be like an array of methods and such that's being loaded to the view.
So How can I load both controllers inside of the same view?
First of all controllers doesn't get loaded inside view instead, you should load a view from a controller and to make the remote request for an API call you don't need to use another controller but you may use it if you have other use of API and need a separate controller. The flow is something like this:
class HomeController extends BaseController {
public function index()
{
// make the api call/remote request
// modify the returned data
// load the view
}
}
Let's rewrite it:
class HomeController extends BaseController {
protected $apiService = null;
public function __construct(ApiService $apiService)
{
$this->apiService = $apiService;
}
public function index()
{
// make the api call/remote request
$apiData = $this->apiService->makeRequest();
// modify the returned data.... then...
// load the view
return View::make(...)->with('apiData', $apiData);
}
}
So, it seems clear that, you should use the API related process in a separate class as a service, maybe a model or a simple repository class and inject it to your HomeController then use it from the controller.
Do all the API stuffs in ApiService and call methods of that class from the HomeController, in this case you may implement the ApiServiceRepository as a concrete class by implementing an interface, i.e. ApiService. So, finally it could be like this:
interface ApiService {
public function makeRequest();
}
// Implement the interface in concrete class
class ApiServiceRepository implements ApiService {
public function makeRequest()
{
// $data = make remote request
// return $data
}
}
Use the class HomeController with __construct as given above and add a IoC binding like:
App::bind('ApiService', 'ApiServiceRepository');
So, you don't have to worry about the dependency injection in the constructor of your HomeController.
BTW, to use a method from another controller, for example ApiController from HomeController you may use something like this:
$apiController = App::make('ApiController');
// Call any method of "ApiController" class/object
$apidata = $apiController->makeCallToMethod();
You may also check this article for understanding the use of repository pattern in Laravel.
I have a piece of code in one of my controllers that I use to call the data for each action and subsequently each view. Rather than repeating the piece of code into each action, what is the best way to create a controller wide function in cakePHP? Or what is best practice?
Example controller:
function get_data($location) {
$orders = $this->Post->find('all',array('conditions' => array('Post.field' => $location));
return $orders;
}
//actual view
function index() {
get_data(waiting);
//etc. etc.
}
//actual view
function view_1() {
get_data(view_1);
//etc. etc.
}
The answer seems to be the fat model, skinny controller approach as outlined in this article.
http://www.sanisoft.com/blog/2010/05/31/cakephp-fat-models-and-skinny-controllers/
You can declare a public function custom_function ($data) in the model and access them in the controller by $this->Model->custom_function($data);
you can use some of this actions:
beforFilter: Called before the controller action
afterFilter: Called after the controller action is run and rendered.
beforeRender: Called after the controller action is run, but before the view is rendered.