Laravel Controller Routes with Parameters - php

I have a Laravel 3 application that has several REST-ful controllers.
The controllers that take no parameters (e.g. a controller that handles the URL /api/books) works fine, but when I try and access the URL of a controller that takes parameters (e.g. /api/book/1), it doesn't work. However, if I append the method name to the URL (e.g. /api/book/index/1), it does work properly.
Is there a way to not be required to use the keyword "index" on a controller?
An example of one of the non-functioning controllers--
<?php
class API_Book_Controller extends Base_Controller {
/**
* Indicates the controller is RESTful
* #var boolean
*/
public $restful = true;
/**
* Fetch a book by ID
* #param integer $id ID number of the book
* #return Response HTTP response
*/
public function get_index($id = null){
$book = Book::find($id);
if(is_null($book)){
return Response::error('404');
}
return Response::eloquent($book);
}

Route::get('api/book/(:num?)', 'API_Book_Controller#get_index');

Related

How do I pass a method with my own constraints in a controller that uses request pattern to display data

Merry Christmass team!
I have a problem trying to figure out how to pass a method with my own constraints in a controller that is bound to request patter paradigm:
Sample Controller Code:
class SampleController
{
protected $model = SampleModel::class;
protected $indexRequest = IndexRequest::class;
}
Request Class
class IndexRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [];
}
Assume I have a method that I want to do something different.Say I want to fetch some data based on some column constraints.
Whats the approach?

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 Auto Routes Like Codeigniter - Custom Solution

When i didn't find any best solution for auto route so i write my code.
Any suggestion will be appreciate.
In your routes.php file write this line at the end of the file
Route::match(["get","post"], '/{controller}/{method?}/{parameter?}', "Routes#index");
Now Create a new class in App\HTTP\Controllers
Routes.php (you can change name)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
class Routes extends Controller
{
public function index($controller,$method="",$parmeter=""){
$controller = ucfirst($controller);
if(empty($method)){
// e.g: example.com/users
// will hit App\Http\Controllers\Users\Users.php Class Index method
return \App::call("App\Http\Controllers\\$controller\\$controller#index");
}
// e.g: example.com/users/list
// will hit App\Http\Controllers\Users\Users.php Class List method
// If user.php has List method then $parameters will pass
$app = \App("App\Http\Controllers\\$controller\\$controller");
if(method_exists($app, $method)){
return $app->$method($parmeter);
}
// If you have a folder User and have multiple class in users folder, and want to access other class
// e.g: example.com/users/groups
// will hit App\Http\Controllers\Users\Groups.php Class Index method
$method = ucfirst($method); //Now method will be use as Class name
$app = \App("App\Http\Controllers\\$controller\\$method");
return $app->index();
}
}
DONE
Now create your Classes in Controllers Folder and it will auto route...
Your file structure E.g:
App
HTTP
Controllers
Users
Users.php
Groups.php
Etc.php
Post
Post.php
Banners
Banners.php
Folder
File.php
Now you have idea, You can change logic according to your style, or you can use this it will work.
I am using Laravel 5.2
As per my understanding, this could be the solution for you.
Laravel has these built in methods for its controller
<?php
class TestsController extends BaseController {
/**
* 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)
{
//
}
}
Route can be defined using following syntax :
<?php
Route::resource('tests', 'TestsController');
These actions will be handled:
GET /tests tests.index
GET /tests/create tests.create
POST /tests tests.store
GET /tests/{id} tests.show
GET /tests/{id}/edit tests.edit
PUT/PATCH /tests/{id} tests.update
DELETE /tests/{id} tests.destroy

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.

Identic lines in each action - should I let them this way or not? - Symfony2

I have a controller which has actions for inserting in the database, updating, deleting and some others, but almost all of the actions contain in them this lines:
$em = $this->getDoctrine()->getEntityManager();
$friend = $em->getRepository('EMMyFriendsBundle:Friend')->find($id);
$user = $this->get('security.context')->getToken()->getUser();
Is this OK, or it's code duplication? I tried to make a property called $em and to have a constructor like this:
public function __construct()
{
$this->em = $this->getDoctrine()->getEntityManager();
}
but it didn't work. As for the queries especially the one with the $id parameter, I don't even know how to separate them in one place, so each action to be able to use them. One way is a function, but is there sense in a function like this? And if yes what should it return? An array?
Please advise me for the optimal way!
What I do, for Symfony2, in the controllers to avoid code duplication is creating a class called Controller.php in which I put the function I often use.
For example :
<?php
namespace YourProject\Bundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller as BaseController;
/**
* Base Controller for xxBundle
*/
class Controller extends BaseController
{
/**
* Get repository
*
* #param string $class class
*
* #return Doctrine\ORM\EntityRepository
*/
protected function getRepository($class)
{
return $this->getDoctrine()->getEntityManager()->getRepository($class);
}
/**
* Set flash
*
* #param string $type type
* #param string $text text
*/
protected function setFlash($type, $text)
{
$this->get('session')->getFlashBag()->add($type, $text);
}
/**
* Returns the pager
*
* #param integer $page Page
* #param integer $perPage Max per page
* #param Doctrine_Query $query Query
*
* #return \Pagination
*/
public function getPager($page = 1, $perPage = 10, $query = null)
{
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$query,
$this->get('request')->query->get('page', 1),
$perPage
);
return $pagination;
}
After creating this controller, you need to make your apps controller extends the controller you've created.
That way, you avoid duplicated code and alias for popular method.
You can do:
private $em;
private $friend;
private $user;
private function init($id==null) {
$this->em = $this->getDoctrine()->getEntityManager();
$this->friend = $id?$this->em->getRepository('EMMyFriendsBundle:Friend')->find($id):null;
$this->user = $this->get('security.context')->getToken()->getUser();
}
Then you can call in your actions
$this->init($id);
or
$this->init();
And you will have
$this->em;
$this->friend;
$this->user;
available. Note that I allowed for the $id parameter not to be set, as I guess that in some actions you will not have it.
If you want this init function to be available in different controllers, create a base controller and extend from it, as suggested in another answer.
The thing you are looking for probably is param converter which maps action param to object directly.
Here is description and some examples:
http://symfony.com/doc/2.0/bundles/SensioFrameworkExtraBundle/annotations/converters.html
edit:
Some more info in an interesting article:
http://www.adayinthelifeof.nl/2012/08/04/multiparamconverter-for-symfony2/
If you have that code only in a couple of controllers you can wrap that code into a protected method for both.
If you think that you can reuse that code in more parts of your application then you should start to think if you need write a validator, use a service or another kind of design

Categories