Can we rename routing resource path names in Laravel like in Ruby on Rails?
Current
/users/create -> UsersController#create
/users/3/edit -> UsersController#edit
..
I want like this;
/users/yeni -> UsersController#create
/users/3/duzenle -> UsersController#edit
I want to do this for localization.
Example from Ruby on Rails;
scope(path_names: { new: "ekle" }) do
resources :users
end
I know this is an old question. I'm just posting this answer for historical purposes:
Laravel now has the possibility to localize the resources. https://laravel.com/docs/5.5/controllers#restful-localizing-resource-uris
Localizing Resource URIs By default, Route::resource will create
resource URIs using English verbs. If you need to localize the create
and edit action verbs, you may use the Route::resourceVerbs method.
This may be done in the boot method of your AppServiceProvider:
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot() {
Route::resourceVerbs([
'create' => 'crear',
'edit' => 'editar',
]); }
Once the verbs have been customized, a resource route registration such as Route::resource('fotos', 'PhotoController') will
produce the following URIs:
/fotos/crear
/fotos/{foto}/editar
It ain't pretty, but you could define multiple routes that use the same controller function. For example:
Route::get("user/create", "UsersController#create");
Route::get("user/yeni", "UsersController#create");
The only (glaringly obvious downside) being that you're routes will get quite cluttered quite quickly. There is a setting in app/config/app.php where you can set/change your locale, and it could be possible to use that in conjunction with a filter to use the routes and then group those routes based on the current local/language, but that would require more research.
As far as I know, there isn't a way to rename resource routes on the fly, but if you get creative you can figure something out. Best of luck!
You can't change the resource url's.
For this you will need to define/create each route according your needs
Route::get("user/yeni", "UsersController#create");
and if you need more than one languages you can use the trans helper function, which is an alias for the Lang::get method
Route::get('user/'.trans('routes.create'), 'UsersController#create');
I just had the same issue. And managed to recreate some sort of custom resource route method. It probably could be a lot better, but for now it works like a charm.
namespace App\Helpers;
use Illuminate\Support\Facades\App;
class RouteHelper
{
public static function NamedResourceRoute($route, $controller, $named, $except = array())
{
$routes = RouteHelper::GetDefaultResourceRoutes($route);
foreach($routes as $method => $options) {
RouteHelper::GetRoute($route, $controller, $method, $options['type'], $options['name'], $named);
}
}
public static function GetRoute($route, $controller, $method, $type, $name, $named) {
App::make('router')->$type($named.'/'.$name, ['as' => $route.'.'.$method, 'uses' => $controller.'#'.$method]);
}
public static function GetDefaultResourceRoutes($route) {
return [
'store' => [
'type' => 'post',
'name' => ''
],
'index' => [
'type' => 'get',
'name' => ''
],
'create' => [
'type' => 'get',
'name' => trans('routes.create')
],
'update' => [
'type' => 'put',
'name' => '{'.$route.'}'
],
'show' => [
'type' => 'get',
'name' => '{'.$route.'}'
],
'destroy' => [
'type' => 'delete',
'name' => '{'.$route.'}'
],
'edit' => [
'type' => 'get',
'name' => '{'.$route.'}/'.trans('routes.edit')
]
];
}
}
Use it like this in the routes.php:
\App\Helpers\RouteHelper::NamedResourceRoute('recipes', 'RecipeController', 'recepten');
Where the first parameter is for the named route, second the controller and third the route itself.
And something like this to the view/lang/{language}/route.php file:
'edit' => 'wijzig',
'create' => 'nieuw'
This results in something like this:
This is not possible in Laravel as they use code by convention over configuration. A resources uses the RESTfull implementation
Therefore you have to stick to the convention of
GET /news/create
POST /news
GET /news/1
GET /news/1/edit
...
Related
I know there is a way to specify the request verb in Yii2's routes like this (in routes.php):
[
'POST users' => 'user/create',
'GET users' => 'user/index',
]
but is there a way to do that inside of a controller in the actions() method? like:
class ExampleController extends Controller {
public function actions() {
return [
'create' => [
'class' => ActionCreate::class,
'verb' => 'POST'
],
'index' => [
'class' => ActionIndex::class,
'verb' => 'GET'
]
];
}
}
I tried:
'GET create' => ActionCreate::class
which yii interpreted as a valid route and /user/create showed a 404
and
'create' => [
'class' => ActionCreate::class,
'verb' => 'GET'
]
which said that 'verb' is an unknown property of ActionCreate
The reason I'm asking this is because I want to make my app use as little explicit routing as possible
The other solution for this is to use the same action for both GET and POST and do things differently on the request method but I would like to keep things separated
Yes, you can do it and VerbFilter is made for that.
Usually you are attaching this behavior in the controller and you should do it like that since you are responsible for the actions added.
If somehow adding it in the controller is not possible, you can implement beforeRun() in the action class like:
public function beforeRun()
{
$verb = \Yii::$app->getRequest()->getMethod();
$allowed = [/*list of allowed uppercased verbs here*/];
if (!in_array($verb, $allowed)) {
\Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed));
throw new \yii\web\MethodNotAllowedHttpException('Method Not Allowed. This URL can only handle the following request methods: ' . implode(', ', $allowed) . '.');
}
return true;
}
This is taken straight from the VerbFilter by the way.
And since this is will be a part of action you can prepare some property that will take the allowed verbs so you will be able to config it in controller's actions() method. But as I said, simply adding it in the controller is much simpler.
I am trying to configure Yii2 url manager in a manner that if a controller name is skipped in url it should call the default controller for action. I have managed to achieve this without action parameter. But got stuck when using parameters in action name.
Here is my route config:
return [
'catalog/category/<alias:[\w-]+>' => 'catalog/default/category',
'catalog/<action:\w+>' => 'catalog/default/<action>',
];
Controller File:
namespace app\modules\catalog\controllers;
use yii\base\Controller;
use app\modules\catalog\models\Categories;
class DefaultController extends Controller
{
public function actionShopbydepartment()
{
$data['categories'] = Categories::findParentSubHierarchy();
return $this->renderPartial('shopbydepartment', $data);
}
public function actionCategory($alias = null)
{
die(var_dump($alias));
$data['category'] = Categories::findCategoryBySlug($alias);
return $this->render('category', $data);
}
}
when I access the following url it loads perfectly.
http://domain.com/index.php/catalog/shopbydepartment
But when i access the below url it called the right function but did not pass the $alias value:
http://domain.com/index.php/catalog/category/appliances
UPDATE:
I have used the following approach for module wise url rules declaration:
https://stackoverflow.com/a/27959286/1232366
Here is what i have in the main config file:
'rules' => [
[
'pattern' => 'admin/<controller:\w+>/<action:[\w-]+>/<id:\d+>',
'route' => 'admin/<controller>/<action>'
],
[
'pattern' => 'admin/<module:\w+>/<controller:\w+>/<action:[\w-]+>/<id:\d+>',
'route' => 'admin/<module>/<controller>/<action>'
],
],
the admin is working fine and this is my first module so rest of the rules are mentioned already
Well just to help other fellows I have retrieve the value of $alias using the following approach:
$alias = \Yii::$app->request->get('alias');
But definitely this is not an accurate answer of the question. I still didn't know what i am doing wrong that i didn't get the value using the approach mentioned in question.
It wirk!
[
'name' => 'lang_country_seller_catalog',
'pattern' => '<lang:\w+>-<country:\w+>/seller/catalog/<module>/<controller>/<action>',
'route' => 'seller/catalog/<module>/<controller>/<action>',
],
[
'name' => 'lang_country_seller_catalog_attributes',
'pattern' => '<lang:\w+>-<country:\w+>/seller/catalog/attributes/<module>',
'route' => 'seller/catalog/attributes/<module>',
],
Working with Yii 2.0.4, I'm trying to use urlManager Rule to preload an object based on a given ID in the URL.
config/web.php
'components' => [
'urlManager' => [
[
'pattern' => 'view/<id:\d+>',
'route' => 'site/view',
'defaults' => ['client' => Client::findOne($id)],
],
[
'pattern' => 'update/<id:\d+>',
'route' => 'site/update',
'defaults' => ['client' => Client::findOne($id)],
],
]
]
If this works, it will not be necessary to manually find and object each time, for some CRUD actions:
class SiteController extends Controller {
public function actionView() {
// Using the $client from the urlManager Rule
// Instead of using $client = Client::findOne($id);
return $this->render('view', ['client' => $client]);
}
public function actionUpdate() {
// Using $client from urlManager Rule
// Instead of using $client = Client::findOne($id);
if ($client->load(Yii::$app->request->post()) && $client->save()) {
return $this->redirect(['view', 'id' => $client->id]);
} else {
return $this->render('edit', ['client' => $client]);
}
}
}
NOTE: The above snippets are not working. They're the idea of what I want to get
Is it possible? Is there any way to achieve this?
If you look closer: nothing actually changes. You still call Client::findOne($id); but now doing it in an unexpected and inappropriate place, and if you look at the comment about default parameter it says:
array the default GET parameters (name => value) that this rule provides.
When this rule is used to parse the incoming request, the values declared in this property will be injected into $_GET.
default parameter is needed when you want to specify some $_GET parameters for your rule. E.g.
[
'pattern' => '/',
'route' => 'article/view',
'defaults' => ['id' => 1],
]
Here we specify article with id = 1 as default article when you open main page of site e.g. http://example.com/ will be handled as http://example.com/article/view?id=1
I can suggest to you add property clientModel in to your controller and then in beforeAction() method check if its update or view action then set
$this->clientModel = Client::findOne($id);
and in your action:
return $this->render('view', ['client' => $this->clientModel]);
I am using zf2 restful api in my web services.
This is my code -
module.config.php -
'login' => array(
'type' => 'segment',
'options' => array(
'route' => '/ws/login[/:id]',
'defaults' => array(
'__NAMESPACE__' => 'Webservices\Controller',
'controller' => 'Login',
),
),
),
This is my controller -
<?php
namespace Webservices\Controller;
use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;
class LoginController extends AbstractRestfulController {
public function getList() {
return new JsonModel(array(
'data' => '',
));
}
/**
* params time, language
* listing category details
* return category details
*/
public function get($id) {
return new JsonModel(array(
'data' => '',
));
}
public function create($requestData) {
print_r($requestData);
die();
}
}
When I post some data into this controller then it redirects into create function.
But requestData variable is NULL.
Raw data method is used for posting. This is my request data
{"reqType":"2","verNo":"test","userName":"test==","deviceIdentifier":"DKZWcdvB50+test+test","password":"test=="}
For some technical reasons I am still using php 5.3.3 and zf2.0.
Sorry I don't have privileges to do comment your question so I just write this as an answer even if this is not.
I'm not sure if your routing is well configured in module.config.php.
There is no action defined in the routing.
Also in your controller the name of the create function shouldn't be createAction ??
I haven't tried but I guess if we're talking about actions in the controller then you're not able to use the parameter list of the action function (only if you defined them in your routing properly). Use instead the following: $this->params()->fromPost(parameterName)
If I misunderstood anything please let me know but I think this problem is not actually related with the zf2 restful API instead how to do routing in zf2 and how to get the parameters inside the actions.
How can I configure Zend Framework 2 route to only to allow POST request type?
I've gone through the documentation but no avail.
EDIT
Here is the portion of my DI code
'cv-create' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/profile/cv/:type/create',
'defaults' => array(
'controller' => 'Application\Controller\ProfileController',
'action' => 'cv_create',
),
),
),
My actual question is, is there any way to inject the request control as a constraint to this route?
You could extend the Zend\Mvc\Router\Http\Segment class and create a slightly modified version of match(). Since match() has the $request parameter it should be as simple as follows:
public function match(Request $request, $pathOffset = null)
{
if (!$request->isPost())
{
return null;
}
return parent::match($request, $pathOffset);
}
Then use this modified class instead of the standard Segment in the routing configuration.
An alternative approach could be to use the AbstractRestfulController in this case.
http://framework.zend.com/apidoc/2.1/classes/Zend.Mvc.Controller.AbstractRestfulController.html
Only implement the create() method.
in class Zend_Controller_Request_Http
You can disable the other request type .