Laravel - Running method of another controller in one controller - laravel

I have UserController and PetController.
In my UserController, I have rewardUser() method.
in my PetController, I'm using the $user variable which indicates the current logged in user.
How I can run my rewardUser() method from my PetController?
I've been trying to user $user->rewardUser(); but for some reasons its not recognizing my method this way.
"Call to undefined method Illuminate\Database\Query\Builder::rewardUser()"

The best way is to use a trait.
Create a trait file, in App\Common.php, for e.g. Then copy the rewardUser() method to the trait.
Your trait file:
namespace App\Forum;
trait Common {
public function rewardUser() {
// Your code here...
}
}
Then in yourUserController.php and PetController.php, use the trait.
// UserController and PetController.php
namespace App\Http\Controllers
use App\Common; // <- Your trait
class UserController extends Controller {
use Common // <- Your trait
public function doSomething() {
// Call the method from both your controllers now.
$this-rewardUser();
}
}
You can use the straight in as many controllers as you want and you can call the method in the straight using $this->methodName().
Very simply and effective.

It seems like you are missing some structure concepts, but if you really need it, you may use the container to do so:
$userController = app()->make(UserController::class);
return app()->call([$userController, 'rewardUser']);

may be you should define the method rewardUser() in the User Model and import it with use App\User

Related

Laravel: When call function from another controller, the relationship query not work

I have two controllers (FirstController, SecondController) that use the same functions, to avoid rewriting them I thought of creating another controller (ThirdController) and subsequently calling the functions through it.
the problem is that if in ThirdController there are relationship query they give me the error that "they don't exist".
example:
User Model
class User extends Authenticatable implements AuthenticatableUserContract
{
use HasFactory, Notifiable;
public function comments(){
return $this->hasMany('App\Models\Comment');
}
ThirdController
class ThirdController extends Controller
{
public static function example($id){
$comments = Comment::find($id)->comments();
return $comments;
}
}
FirstController/SecondController
public function example2(Request $request){
return ThirdController::example($request->id);
When call the route it give me error:
BadMethodCallException: Method Illuminate\Database\Eloquent\Collection::comments does not exist.
my questions are:
Is there any better method instead of creating a third controller?
Is there a solution to this?
p.s. I know I could very well build the queries without exploiting the relationship, but where's the beauty of that? :D
You do not need to create 3rd controller. You can create a class and here you write the query in a function and use this class in controller1 and controller2 by dependency injection.
First thing that's not a best practice to define a static method in one controller and call it in another controller (not recommended way).
Second you're calling Comment::find($id) with comments() relation. you should call a User class, like below snippet:
class ThirdController extends Controller
{
public static function example($id){
$comments = User::find($id)->comments();
return $comments;
}
}
RECOMEND APPROACH:
Creat a one seperate service/repository class in which you'll define a common method i.e. getUserComments() and use it in both or all of three controllers (upto your requirement/needs). By this way you implementations will be on a centric place.
If you want learn about Repository pattern you can get basic idea from: Article#1

How to autoload custom class in Laravel?

I wrote custom class with method that returns array.
I need to autoload this class like Auth() class in Laravel, that I could get access to it from any controller not using use
Create one custom helper file
and add function
if (! function_exists('yourcustomclass')) {
function yourcustomclass()
{
use App\Http\yourcustomclassname;
return new yourcustomclassname()
}
}
you can use yourcustomclass() function from anywhere to get yourcustomclassname class object
When accessing class/function from other namespace than you're currently in you have to use Fully-Qualified Class Name (or type use, but you don't want to do that), so instead of Auth::user() you need to write \Auth::user()
\ at the beginning means that class is located in root namespace
Why don't you write super method(s) in App\Http\Controllers\Controller?
Simply call super method(s) in the subclass which extends Controller

Loading classes only if function is called

I have one FrontendController that get all requests from frontend. As all URLs are like:
Route::get('/{slug}', 'FrontendController#index');
I need to use the same controller to get all Entities. My FrontendController looks like this:
use Auth;
use App;
use Cache;
use URL;
use Redirect;
use Session;
use Response;
use App\Country;
use App\I18n;
use App\User;
use App\CMS;
use App\CMSPageContent;
use App\Slugs;
use App\News;
...
...
use App\Http\Controllers\Controller;
I have several questions regarding this:
Are ALL these services injected in each execution of FrontendController. Because maybe I'm loading the entire code and It will make my page load slow.
If answer to previous question is yes, can I load a library only if one function is called?
Is it a good way to solve the slug problem? Because all URLs have one piece only for SEO reasons and I don't know other way to treat the routes.
It varies depending on how you are using the code. For example if you required the Auth login method, but nothing else, it would be a waste of resources to initialise a model or inject the model into that function.
For example say this is a function in my model
public function doSomething()
{
//Do stuff
}
I would like to call this function in my Controller. I have a few options, I could reference the model at the top of my controller
use App\MyModel;
I believe this doesn't actually initiate the model, it acts like a reference, so that when it is called, the system knows where to find it.
I could inject it into my function
public function myControllerFunction(\App\MyModel $model)
{
return $model->doSomething();
}
This uses the most resources due to the model being assigned to the $model variable, which is fine if you need the models eloquent for database actions and its functions. If you require just one function from that model then a static call would use less resources.
In your model make the function static
public static function doSomething()
{
}
Then in your controller you can call it like this
public function myControllerFunction()
{
return \App\MyModel::doSomething();
}
This would use the less resources and would clean up the code a bit as you wouldn't need to keep referencing your uses at the top of the controller

How to Call a controller function in another Controller in Laravel 5

im using laravel 5.
I need to call a controller function but this should be done in another controller.
I dont know how to do this
public function examplefunction(){
//stuff
}
And i have a Route for this function, so at
public function otherfunctioninothercontroller(){
// I need examplefunction here
}
how Can i do this?
1) First way
use App\Http\Controllers\OtherController;
class TestController extends Controller
{
public function index()
{
//Calling a method that is from the OtherController
$result = (new OtherController)->method();
}
}
2) Second way
app('App\Http\Controllers\OtherController')->method();
Both way you can get another controller function.
If they are not in the same folder, place use namespace\to\ExampleClass; on top of your file, then you are able to instantiate your controller.
You can simply instantiate the controller and call the desired method as follows
FirstController.php:
namespace App\Http\Controllers;
class FirstController extends Controller {
public function examplefunction() {
// TODO: implement functionality
}
}
SecondController.php:
namespace App\Http\Controllers;
class SecondController extends Controller {
public function test() {
$object = new FirstController();
$object->examplefunction();
}
}
Now, after i've answered the question, i would like to add the following comment:
Controllers are classes, all rules that applies to normal classes can be applied to them
However, instantiating a controller directly inside another controller to call a desired method signifies a problem in your design for the following 2 reasons:
A controller cannot obtain an instance of another controller directly
Controller should contain as little business logic as possible, and if possible none
The closest possible solution to what you want (WITHOUT BREAKING MVC) is to make an HTTP request to the route that points to the desired method (using cURL, for example) and read the response as the returned data
But this still doesn't make much sense in this scenario because after all you're making an HTTP request from a method in a controller in your project on your server to a method in a controller in your project on your server, seems like unnecessary overhead, right ?
As i said earlier, a controller should contain as little business logic as possible because the logic should stay inside specialized classes (commonly known as Service Classes), and when a processing is requested the controller simply delegates the job of processing to the appropriate service class which does the processing and returns the results to the controller which in turn sends it back as a response
Now imagine if you've the following scenario:
We've got an application that consists of 3 functionalities:
A user can register an account from web application
There's a mobile application that talks to an API to register a user
There's an admin panel, which he can use to add new user
Obviously you need to create 3 controllers, but those controllers contains repeated logic, would you copy/paste the code everywhere ?
Why not encapsulate this logic inside a service class and call it from the controller when needed ?
Let's say I have Controller1 and Controller2. I want to call a function of Controller1 from inside a function placed in Controller2.
// Controller1.php
class Controller1 {
public static function f1()
{
}
}
And on the other controller:
// Controller2.php
use App\Http\Controllers\Controller1;
class Controller2 {
public function f2()
{
return Controller1::f1();
}
}
Points to be noted:
f1() is declared static
A call to a controller from inside another controller is a bad idea. There is no sense of meaning of controllers then. You should just redirect to web.php to save safe whole architecture like this:
class MyController {
public function aSwitchCaseFunction(Request $requestPrm){
...
//getting path string from request here
...
switch($myCase){
case CASE_1:
return redirect()->route('/a/route/path');
....
}
}
}

Access an object of one class in other codeigniter

I have two controller classes in my codeigniter application, say class A and B.I just want to create an object of class A and access the functions declared in class A from class B.Something like:-
class A extends someclass
{
public function function1(){
$this->load->view('welcome_message');
}
}
}
class B extends someclass2
{
protected $object;
public function __construct()
{
parent::__construct();
$this->objectA = new A();
}
}
}
I want to access the function function1 from class B using the object objectA. How can i do this?
Please help.
Thanks
well actually this is not the proper way in codeigniter. Actually when you have common functions in and you want to use them in 2 or more controllers. The best way is to create base controller in core folder with name of MY_Contoller and extend it from CI_Contoller. Write your common function in MY_Contoller. Now you have to extend all your controllers from MY_Contoller instead of CI_Contoller. You can do the same with Model.
Cross-controller access goes against CI best practice.
Either inherit both controllers from a controller that holds this common functionality (don't forget to prefix the function with '_' so it's inaccessible via url routing) or create a library that contains your re-usable functionality. A helper can also work.

Resources