I'm using Laravel version 6.x. I have created one helper function called GraphqlApi.
My helper class will look like below:
<?php
namespace App\Helpers;
/**
* GraphqlApi class
*/
class GraphqlApi
{
public function __construct() {
echo "test";die;
}
}
But whenever I call any function from helper class construct function is not being called.
Is there any way to make it work?
if you always want the constructor to be called when you are calling other methods.
First, you can not have static method.
Second, call the method this way.
$graphqlApi = new GraphqlApi();
$result = $graphqlApi->getGuzzleRequest();
This way the constructor will be called.
Related
My ide typhints a few different namespaces for rendering a view in my controller and i'm not sure which one i'm supposed to use:
class PostsController extends Controller
{
public function index() : View
{
return view('posts.index');
}
}
The "view" function returns multiple types:
#return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
So which one am i supposed to use? \Illuminate\Contracts\View\View or \Illuminate\Contracts\View\Factory
What is the difference?
Why is it returning two different types instead of one? I code php in a strict way because i prefer it for readable and less error prone code, in my opinion this is a bad way of doing it and as you can see is causing confusion; a method should only be allowed one return type, create multiple methods if need be.
EDIT
Thank you for your input everyone, i have come up with the following that allows me to use the facade and the contract without producing typhint errors in my ide:
<?php
namespace App\Http\Controllers;
use Illuminate\Contracts\View\View as ViewContract;
use Illuminate\Support\Facades\View as ViewFacade;
/**
* Class PostsController
* #package App\Http\Controllers
*/
class PostsController extends Controller
{
/**
* #return ViewContract
*/
public function index() : ViewContract
{
return ViewFacade::make('posts.index');
}
}
So i can call View:make() and return the contract that View:make() returns.
EDIT 2
Using the view() helper i can condense further, i am aliasing with ViewContract just for my benefit of knowing which namespace i'm using:
<?php
namespace App\Http\Controllers;
use Illuminate\Contracts\View\View as ViewContract;
/**
* Class PostsController
* #package App\Http\Controllers
*/
class PostsController extends Controller
{
/**
* #return ViewContract
*/
public function index() : ViewContract
{
return view('posts.index');
}
}
I’ll try and address each of your questions.
In your instance, type-hint Illuminate\Contracts\View\View or the concrete implementation (Illuminate\View\View).
I’ll cover this in 3.
You’re using the view global helper function. It can return different types because, well, it can. If you don’t pass a parameter to view() then it will return a view factory instance. If you do pass a parameter (like you have in your usage), then it will return an instance of the view named by the first parameter (if such a view exists). So that’s why the view() helper function is typed to return multiple different types. Because depending on how you use it, it can return a different type.
You mean: \Illuminate\View\View.
public function index(): \Illuminate\View\View
{
return view('posts.index');
}
view() is a helper of Illuminate\Support\Facades\View facade.
return view('posts.index');
Same as :
use Illuminate\Support\Facades\View;
return View::make('posts.index');
See the documentation of Creating & Rendering Views
When a request comes to Laravel controller through application router, how can we determine which method is called inside that controller? I mean inside constructor or magic methods of the controller. Is it possible to know?
Consider the method that is called exists. So __call would not be the solution.
I have this Route:
Route::get('exam', [ExamController::class,'index']);
And I want to get index inside ExamController class. maybe in side __construct or ...
public function __construct()
{
// here I want to access the name of called method
}
__call magic method just give the method name if the method is'nt exist:
public function __call($method, $parameters)
{
// I have access to $method name here (index)
}
You can use the __FUNCTION__ or __METHOD__ PHP constants to obtain information about the function or class and function:
class SomeClass
{
public function aFunction()
{
echo __FUNCTION__;
}
public function anotherFunction()
{
echo __METHOD__;
}
}
$obj = new SomeClass();
$obj->aFunction(); // aFunction
$obj->anotherFunction(); // SomeClass::anotherFunction
Update
Let's assume whilst you might not have a function defined for a specific route, you know the name of a route you want to apply a specific middleware to. You can apply middelware to specific functions from the controller constructor:
public function __construct()
{
$this->middleware('auth', ['only' => ['index', 'create']]);
}
Alternatively just specify the middleware required for the route on the route definition.
I make controller by using php artisan make:controller newsController --resource
And after that when I go to my controller in function index, I want to add Request $request
public function index(Request $request)
{
}
It's return error:
Declaration of
App\Http\Controllers\Admin\NewsController::index(Illuminate\Http\Request
$request) should be compatible with
App\Http\Controllers\Controller::index()
How to fix it? I try many way but it still didn't work!
EDIT — Controller
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
UPDATED — Routes
Route::post('admin/news', 'Admin\NewsController#store');
Route::resource('admin/news', 'Admin\NewsController');
It's quite simple, just create your Resource controller without the index route Or Create new get route, like this:
Route::resource('admin/news', 'Admin\NewsController', ['except' => ['index']]);
Then add your route before the resource declaration, something like this:
Route::post('admin/news', 'Admin\NewsController#index');
Route::resource('admin/news', 'Admin\NewsController', ['except' => ['index']]);
Hope this helps you!!
This doesn't require any Laravel work arounds.
Fix:
a) Remove the index method from the base controller
or
b) Make the index method in the base controller take a Illuminate\Http\Request as an argument and use that same method signature in every controller's index method that inherited from the base in the entire application.
or
c) Figure out why there is an index method defined in the base in the first place and, if needed, move it to a trait to use in child classes instead. (allows you to override the method completely)
b is not a good option, it is just to illustrate a point
Issue demonstrated:
class Foo
{
public function index()
{
//
}
}
class Bar extends Foo
{
public function index(\Illuminate\Http\Request $request)
{
}
}
Declaration of Bar::index(Illuminate\Http\Request $request) should be compatible with Foo::index()
You want to override the index action.
You also want to pass parameters into this index action.
The App\Http\Controllers\Controller::index() does not take parameters.
So they are not "compatible".
Try this "helper-funtion" way:
public function index() {
$request = request() // use the helper function
// ...you code here...
}
You can disable index from resources and define route with different method name before or after resource:
Route::get('resources', 'ResourceController#getResources');
Route::resource('resources', 'ResourceController', $restResource)->except(['index']);
I have two methods and I want in first method to call the other method. They are in the same controller. I tried in this way but I'm getting error:
Call to undefined method Controller_User::getUser()
My controller looks like that:
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_User extends Controller {
public function action_index (){
$id = $this->request->param('id');
$user = self::getUser($id);
}
public function action_getUser ($id){
//some code here
}
}
Both functions are in same class so use $this-> to call other method in same class in your case as kingkero mentioned in comment user $this->action_getUser($id)
If I want to set a variable that my whole controller can access, how do I do it?
Right now, in every function I am setting
$id = $this->session->userdata('id');
I'd like to be able to access $id from any function w/o defining it for each controller. :)
If there's a better way, I'm all ears! I'm a noob!
To elaborate on Koo5's response, you'll want to do something like this:
class yourController extends Controller {
// this is a property, accessible from any function in this class
public $id = null;
// this is the constructor (mentioned by Koo5)
function __construct() {
// this is how you reference $id within the class
$this->id = $this->session->userdata('id');
}
function getID() {
// returning the $id property
return $this->id;
}
}
See the manual for more information on PHP properties and constructors. Hope that helps!
If with global you mean the scope of a single controller, the above answers are correct. If you want to access variables from multiple controllers, I recommend defining a BaseController class and then extending your normal controllers to inherit from that BaseController:
class yourController extends BaseController {}
I use this all the time for both global variables and methods.
Define that very line in a constructor only
You can use this method too inside your controller
function __construct() {
// this is how you reference $id within the class
DEFINE("userId",$this->session->userdata('id'));
}
And Call It As :
function getID() {
// returning the $id property
return userId;
}