How to pass data from routes group to its controllers? - php

I have a routes group in Laravel that gets a parameter like below:
Route::group(['prefix' => '{ProjectCode}'], function () {
Route::get('/categories', 'CategoriesController#Categories');
Route::get('/add-category', 'CategoriesController#AddCategory');
});
The ProjectCode is an id, that is used to get some data from the database
I want to pass the retrieved data to controllers that they are in sub of the route group and avoid getting data in every function in controller

You may use "Implicit/Explicit Route Model Binding", assuming you have Project model, you can have this controller method (use camelCase for parameters and controllers' methods name not PascalCase):
Route::group(['prefix' => '{projectCode}'], function () {
Route::get('/categories', 'CategoriesController#pategories');
Route::get('/add-category', 'CategoriesController#addCategory');
});
class CategoriesController extends Controller
{
/**
* Display a listing of the resource.
*
* #param Request $request
* #return \Illuminate\Http\Response
*/
public function categories(\App\Project $projectCode)
{
//
}
}
You may wish to use your own resolution binding, override the resolveRouteBinding on your model:
/**
* Retrieve the model for a bound value.
*
* #param mixed $value
* #param string|null $field
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
return $this->where($field ?? $this->getRouteKeyName(), $value)->first();
}
See Laravel docs for more info.

Related

method not calling laravel 5.1 to laravel 8.* upgrade

I need some clarification with dynamic controller method
i upgrading the laravel 5.1 to 8.*, all is done, but only one bug,
my url is admin/admin-profile in 5.1 is working fine, but laravel 8 is not working 404 page error is showing.
this url will call method getAdminProfile(){ } but is not calling.
if this functionality is not available in laravel 8, then how can i manage this, if single url i will create route, but my application have more than 100 url like this, so please help me to solve this...
i was check this issues by compare all file both laravel 5.1 and laravel 8
missing one file to capture the like this problem from ControllerInspector from routing folder.
so please help to solve this..
i can't write each method in web.php
Route::controller('admin', 'AdminController');
class AdminController extends BaseController {
public function getIndex()
{
//
}
public function getAdminProfile()
{
//
}
public function anyLogin()
{
//
}
}
Resource Controller
If Resource Controller can handle your need so use that:
Documentation: https://laravel.com/docs/8.x/controllers#resource-controllers
and it's like below:
Routing:
use App\Http\Controllers\PhotoController;
Route::resource('photos', PhotoController::class);
----------------
If Resource Controller is not what you want:
you can get url and transfer url to controller function, for example:
router file getting any url after admin\
Route::prefix('admin')->group(function () {
Route::get('/{my_url?}', [AdminControlle:class, 'handle'])->where('my_url', '(.*)');
});
AdminController
public function handle(){
// get url segments after admin/ - if url is like your_domain.com/admin/...
$segments = array_slice(request()->segments(), 1);
// Translate array of segments to function name - implement by you
$functionName='';
// calling function with knowing its name
$functionName() // or can use call_user_func($functionName);
}
*Note: be aware that this dynamic route handling doesn't provide a solution for dynamic handling of http methods (post, get, patch, ...).
in this example i used GET method.
I just add below code in router.php
/**
* Register an array of controllers with wildcard routing.
*
* #param array $controllers
* #return void
*
* #deprecated since version 5.1.
/
public function controllers(array $controllers)
{
foreach ($controllers as $uri => $controller) {
$this->controller($uri, $controller);
}
}
/*
* Prepend the last group uses onto the use clause.
*
* #param string $uses
* #return string
*/
protected function prependGroupUses($uses)
{
$group = end($this->groupStack);
return isset($group['namespace']) && strpos($uses, '\\') !== 0 ? $group['namespace'].'\\'.$uses : $uses;
}
/**
* Route a controller to a URI with wildcard routing.
*
* #param string $uri
* #param string $controller
* #param array $names
* #return void
*
* #deprecated since version 5.1.
*/
public function controller($uri, $controller, $names = [])
{
$prepended = $controller;
// First, we will check to see if a controller prefix has been registered in
// the route group. If it has, we will need to prefix it before trying to
// reflect into the class instance and pull out the method for routing.
if (! empty($this->groupStack)) {
$prepended = $this->prependGroupUses($controller);
}
$routable = (new ControllerInspector)
->getRoutable($prepended, $uri);
// When a controller is routed using this method, we use Reflection to parse
// out all of the routable methods for the controller, then register each
// route explicitly for the developers, so reverse routing is possible.
// print_r($routable);
foreach ($routable as $method => $routes) {
foreach ($routes as $route) {
$this->registerInspected($route, $controller, $method, $names);
}
}
$this->addFallthroughRoute($controller, $uri);
}
/**
* Register an inspected controller route.
*
* #param array $route
* #param string $controller
* #param string $method
* #param array $names
* #return void
*
* #deprecated since version 5.1.
*/
protected function registerInspected($route, $controller, $method, &$names)
{
$action = ['uses' => $controller.'#'.$method];
// If a given controller method has been named, we will assign the name to the
// controller action array, which provides for a short-cut to method naming
// so you don't have to define an individual route for these controllers.
$action['as'] = Arr::get($names, $method);
$this->{$route['verb']}($route['uri'], $action);
}
/**
* Add a fallthrough route for a controller.
*
* #param string $controller
* #param string $uri
* #return void
*
* #deprecated since version 5.1.
*/
protected function addFallthroughRoute($controller, $uri)
{
$missing = $this->any($uri.'/{_missing}', $controller.'#missingMethod');
$missing->where('_missing', '(.*)');
}
Now is working normally

Laravel nova make resource show only the data of the user

I am trying to do something that seems to go out of the box with how laravel-nova works ...
I have a Batch model/ressource that is used by super admins. Those batch reeports belongs to sevral merchants. We decided to add a layer of connection to are portal and allow merchants to log in and see there data. So obviously, when the merchant visites the batch repport page, he needs to see only data related to it's own account.
So what we did was add the merchant id inside the batch page like this:
nova/resources/batch?mid=0123456789
The problem we then found out is that the get param is not send to the page it self but in a subpage called filter ... so we hacked it and found a way to retreive it like this:
preg_match('/mid\=([0-9]{10})/', $_SERVER['HTTP_REFERER'], $matches);
Now that we have the mid, all we need to do is add a where() to the model but it's not working.
Obviously, this appoach is not the right way ... so my question is not how to make this code work ... but how to approche this to make it so that merchants can only see his own stuff when visiting a controller.
All i really need to is add some sort of a where('external_mid', '=' $mid) and everything is good.
The full code looks like this right now:
<?php
namespace App\Nova;
use App\Nova\Resource;
use Laravel\Nova\Fields\ID;
use Illuminate\Http\Request;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\HasMany;
use Laravel\Nova\Fields\Currency;
use Laravel\Nova\Fields\BelongsTo;
use App\Nova\Filters\StatementDate;
use Laravel\Nova\Http\Requests\NovaRequest;
class Batch extends Resource
{
/**
* The model the resource corresponds to.
*
* #var string
*/
//
public static function query(){
preg_match('/mid\=([0-9]{10})/', $_SERVER['HTTP_REFERER'], $matches);
if (isset($matches['1'])&&$matches['1']!=''){
$model = \App\Batch::where('external_mid', '=', $matches['1']);
}else{
$model = \App\Batch::class;
}
return $model;
}
public static $model = $this->query();
/**
* The single value that should be used to represent the resource when being displayed.
*
* #var string
*/
public static $title = 'id';
/**
* The columns that should be searched.
*
* #var array
*/
public static $search = [
'id','customer_name', 'external_mid', 'merchant_id', 'batch_reference', 'customer_batch_reference',
'batch_amt', 'settlement_date', 'fund_amt', 'payment_reference', 'payment_date'
];
/**
* Indicates if the resource should be globally searchable.
*
* #var bool
*/
public static $globallySearchable = false;
/**
* Get the fields displayed by the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function fields(Request $request)
{
return [
ID::make()->hideFromIndex(),
Text::make('Customer','customer_name'),
Text::make('MID','external_mid'),
Text::make('Batch Ref #','batch_reference'),
Text::make('Batch ID','customer_batch_reference'),
Text::make('Batch Date','settlement_date')->sortable(),
Currency::make('Batch Amount','batch_amt'),
Text::make('Funding Reference','payment_reference')->hideFromIndex(),
Text::make('Funding Date','payment_date')->hideFromIndex(),
Currency::make('Funding Amount','fund_amt')->hideFromIndex(),
// **Relationships**
HasMany::make('Transactions'),
BelongsTo::make('Merchant')->hideFromIndex(),
// ***
];
}
/**
* Get the cards available for the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function cards(Request $request)
{
return [];
}
/**
* Get the filters available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function filters(Request $request)
{
return [
];
}
/**
* Get the lenses available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function lenses(Request $request)
{
return [];
}
/**
* Get the actions available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function actions(Request $request)
{
return [];
}
}
In Laravel Nova you can modify the result query of any Resource by adding the index Query method. This method allows you to use Eloquent to modify the results with any condition you define.
I understand you just need to maintain the $model property with the model with the default definition and modify the results in the indexQuery method:
...
public static $model = \App\Batch::class;
public static function indexQuery(NovaRequest $request, $query)
{
// Using the same logic of the example above. I recommend to use the $request variable to access data instead of the $_SERVER global variable.
preg_match('/mid\=([0-9]{10})/', $_SERVER['HTTP_REFERER'], $matches);
if (isset($matches['1'])&&$matches['1']!=''){
return $query->where('external_mid', '=', $matches['1']);
}else{
return $query;
}
}
...
About the use of the PHP Global Variable, I recommend you to use the laravel default request() to look into your URL. You can use something like this $request->mid to read the value from the mid value in the URL.

PHP laravel automatic routing

I am using laravel 5.5 and I am trying to use a automatic route to the controller but it isn't working
In the web.php(the routing file for this version)
I have the follow line
Route::resource('panel', 'panel');
Route::resource('/', 'HomeController');
In the panel I have the follow actions
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class panel extends Controller{
public function index(){
return \View::make('panel.index');
}
public function registrar(){
return \View::make('panel.registrar');
}
}
but it's only calling the index() view
the registrar() view is not being called when user acess the url
site.com/panel/registrar
the follow erro is printing in the screen
"Method [show] does not exist on [App\Http\Controllers\panel]."
I tried to use the base_controller but it don't work too
"Class 'App\Http\Controllers\Base_Controller' not found"
is there an way to identify these actions ?
Resource routing sets up 7 specific routes, that is 7 specific methods you need on the controller, 7. If you dont want all 7 of those routes you have to define it that way.
Resource routing is not implicit controllers. It does not look at the method on the controller then make routes .. Resource routing is a 'specific' thing. We do not have implicit controllers any more in Laravel as there is really no point.
Laravel 5.5 Docs - Controllers - Resource Controllers
You have routes that are created that point to methods that don't exist, that is what the error is.
Also, the first argument to Route::resource is a resource 'name', not a PATH. It is not technically a URI. It is a name of a resource.
Route::resource('/', ...) // not a name
This is a resource controller with basic CRUD operations, so in order to work you have to define the rest methods like in your case you should add a method show() and then render the view you want in that method.
A resource controller must have the following methods defined:
class TestController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
And base controller obviusly it is not Base_Controller but its Controller
For more please reffer here Laravel 5.5 Resource Controllers
Change this resourse to simple get , if you don't need all resource methods
Route::get('/panel', 'panel#index');
Route::get('/panel/registrar', 'panel#registrar');
And use home instead just / to get unconflicted url
Route::resource('home', 'HomeController');

Laravel Undefined Offset: 1 - cause by routing

I get the error when trying to make a post call to /api/subject/search
I assume it's a simple syntax error I'm missing
I have my api routes defined below
Route::group(array('prefix' => 'api'), function()
{
Route::post('resource/search', 'ResourceController');
Route::resource('resource', 'ResourceController');
Route::post('subject/search', 'SubjectController');
Route::resource('subject', 'SubjectController');
Route::resource('user', 'UserController');
Route::controller('/session', 'SessionController');
Route::post('/login', array('as' => 'session', 'uses' => 'SessionController#Store'));
});
And my controller is mostly empty
class SubjectController extends \BaseController
{
public function search()
{
$subjects = [];
if((int)Input::get('grade_id') < 13 && (int)Input::get('grade_id') > 8)
$subjects = Subject::where('name', 'like', '%HS%')->get();
else
$subjects = Subject::where('name', 'not like', '%HS%')->get();
return Response::json([
'success' => true,
'subjects' => $subjects->toArray()
]);
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
You need to specify the method.
try
Route::post('subject/search', 'SubjectController#search');
See the named route example:
Laravel Docs
In your case I think search is not resolved by the controller to load the search() method. You are also sending a POST for search functionality and I guess it's better to do a GET request since POST and PUT are for storing data.
Conventions
When creating API's it's a good thing to stick to naming conventions and patterns.
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
Solution
Your route could be simpler like this: api.yourdomain.com/api/subject?search=term1,term2. Doing this with a GET query makes it going to the index() method. There you can check the GET params and do your search stuff and return.
Check this for the cleanest and truely RESTful way to make an API in Laravel:
How do I create a RESTful API in Laravel to use in my BackboneJS app
I got same error when accessing object at index of an empty array in view blade php file.

Laravel 4. default controller route wont accept arguments

I have a RESTful controller for my users to handle the viewing of a users profile.
The problem is this:
I want the url to look like this www.example.com/user/1
This would show the user with the id of 1. The problem is that when i define the getIndex method in the UserController it wont accept the id as an argument.
Here is my routes.php portion:
Route::controller('user', 'UserController');
Now, it is my understanding that getIndex is sort of the default route if nothing else is supplied in the url, and so this:
public function getIndex() {
}
within the UserController will accept routes,
"www.example.com/user/index"
and
"www.example.com/user"
and it does!
However, if I include an argument that it should take from the url, it no longer works:
public function getIndex($id) {
//retrieve user info for user with $id
}
This will only respond to
"www.example.com/user/index/1"
and not
"www.example.com/user/1"
How can i make the latter work? I really do not want to clutter up the url with the word "index" if it is not necessary.
If you are planning to do this, the best way is to use RESTful controllers.
Change your route to this one,
Route::resource('user', 'UserController');
Then generate a controller using php artisan command,
php artisan controller:make UserController
This will generate your controller with all RESTful functions,
<?php
class UserController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index() // url - GET /user (see all users)
{
//
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store() // url - POST /user (save new user)
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id) // url - GET /user/1 (edit the specific user)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id) // url - PUT /user/1 (update specific user)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id) // url - DELETE /user/1 (delete specific user)
{
//
}
}
For more info, see this one Laravel RESTful controller parameters
To display www.example.com/user/1 on address bar you should use show method. In Laravel, restful controller by default create 7 routes. Show is one of them.
in your controller create a method like the following:
public function show($id)
{
// do something with id
$user = User::find($id);
dd($user);
}
Now, Browse http://example.com/user/1.

Categories