How do I set dynamic prefixes in Laravel routes - laravel-4

heres the situation - I'm building a site thats region based and I need to set it up so that the first segment of the route is a region i.e. of the type:
www.mysite.com/{region}
Currently I have routes set up like this:
www.mysite.com/businesses
www.mysite.com/businesses/show
I've tried a number of tricks but for some reason I can't get this to work:
www.mysite.com/{region}/businesses
in such a way that I need to filter by the {region} variable and that the {region} variable has to prepend every url in the site, also the {region} variable should also be accessible in the controller. I had a look at the localization options except I don't want to change languages here. I'm looking for implementing something of the following:
www.mysite.com/barcelona/businesses
www.mysite.com/new-york/businesses
I already have a table of all regions and slugs and the required relationships. Just trying to get this to work.

Add the region route on top of all other routes, I have similar feature for a project and that fixed it for me.
Route::get('{region?}/businesses', array(
'as' => 'regionBusinesses',
'uses' => 'RegionBusinessesController#getBusinesses'
))->where('region', '.*');
In your Controller
class RegionBusinessesController extends SomeController {
public function getBusinesses($region) {
return View::make('YOUR_VIEW_NAME')->withBusinesses($this->YOUR_MODEL->FETCH_BUSINESSES_METHOD($region));
}

Related

How can I customize controller output based on developer supplied parameters with Laravel 8?

Is there any way to customize what a controller returns based on a parameter (not a query parameter) provided in a route? For example, if there are two modes of display, but it depends on the URL accessed as far as which way it's displayed.
A simplified, made up example:
class MyController extends Controller
{
// $display_mode can be "large" or "small"
public function show($display_mode = null)
{
...
}
}
Route:
For /page1 I want $display_mode to be "large", for /page2, I want it to be "small." How do I pass that in via the function parameter? This would be the preferred way, but if Laravel does this a different way, let me know.
Route::get('/page1', [MyController::class, 'show']);
Route::get('/page2', [MyController::class, 'show']);
To get a better idea of what I want to accomplish. Say the controller function has five different customizable parameters based on both display and business logic. I can't know in advance what options will apply to the pages that the developer creating routes will want to display. I just want to make those options available.
Also, the developer making the routes does not want to make URLs with ugly paths such as mypage/large/tiled/system-only. The end user doesn't need to know about all of the options passed in as parameters to a function.
Rather, the routes should only be /a, /b, and /c and each of those routes underneath the hood represents zero to five customizable options by passing in the options as parameters to the controller function.
edit:
I tried the defaults() method and it works well. Note that in order for it to work, a separate default() call has to be made for each function parameter. For example:
Route::get('/login/main', [WAYFController::class, 'wayf'] )
->defaults('tiledUI', false)
->defaults('showAffiliateLogin', true)
->defaults('type', 'full');
Yea, you can do this. You can use the defaults method of the Route to pass a default value for a parameter:
Route::get('testit', function ($display_mode) {
dump($display_mode);
})->defaults('display_mode', 'large');
You can use this to pass arbitrary data to the 'action'.
Another use-case for this is if you had something like a PageController to display a single page but don't want the routes to be dynamic and instead explicitly define the routes you will have:
Route::get('about-us', [PageController::class, 'show'])
->defaults('page', 'about-us');
Route::get('history', [PageController::class, 'show'])
->defaults('page', 'our-history');
The Route class is Macroable so you could even create a macro to define these defaults on the route:
Route::get('about-us', [PageController::class, 'show'])
->page('about-us');
The Router itself is also Macroable so you could define a macro to define all of this into a single method call:
Route::page('about-us', 'about-us');

Laravel Route Controller issue

I am trying to add a new route to my application and can't seem to get it to work. I keep getting a 404 error. It looks like the physical path is looking at the wrong directory. Currently looking at D:\Web\FormMapper\blog\public\forms but should be looking at D:\Web\FormMapper\blog\resources\view\layout\pages\forms.blade.php
My request URL:
http://localhost/FormMapper/ /works fine
http://localhost/FormMapper/forms /doesn't work
http://localhost/FormMapper/forms.php /No input file specified.
my FormsController:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class FormsController extends Controller
{
public function index()
{
return view('layouts.pages.forms');
}
}
My web.php:
Route::get('/', function () {
return view('layouts/pages/login');
});
Route::get('/forms', 'FormsController#index');
My folder structure looks like this:
My config/view.php
return [
'paths' => [
resource_path('views'),
],
'compiled' => env(
'VIEW_COMPILED_PATH',
realpath(storage_path('framework/views'))
),
];
you must use dot for this. In your controller change to this:
return view('layouts.pages.forms');
If your route only needs to return a view, you may use the Route::view method. Like the redirect method, this method provides a simple shortcut so that you do not have to define a full route or controller. The view method accepts a URI as its first argument and a view name as its second argument. In addition, you may provide an array of data to pass to the view as an optional third argument:
Route::view('/', 'layouts.pages.login');
Route::view('/forms', 'layouts.pages.forms', ['foo' => 'bar']);
Check docs
After tracking digging deeper I determined that the issue was that IIS requires URL rewrite rules in place for Laravel to work properly. The index.php and '/' route would work b/c it was the default page but any other pages wouldn't. To test this I used the
php artisan serve
approach to it. and everything worked properly. Unfortunately I am unable to do this in production so I needed to get it to work with IIS.

Laravel Language prefix with additional parameters

Quick question that is already killing me for days.
With Laravel I am trying to use different languages.
English and Japanese
This works in the route like this.
Route::group([
'prefix' => '{lang}',
'where' => ['lang' => '(jp|en)'],
'middleware' => 'Language'
], function() {
Route::get('/blogs', 'BlogController#index')->name('main-blog');
Route::get('/blog/{postId}/{postTitle}', 'BlogController#post');
});
This works when I am visiting the "/blogs" page.
It changes between languages.
Now when I visit the "/blog/{postId}/{postTitle}" page I can't access the posted parameter anymore within my controller.
Somehow it only shows the "lang" parameter.
What would be the right way to access a parameter when using a prefix.
When I don't use the prefix it works like a charm.
My Controller;
public function post($blog_id, $blog_title)
{
// Do something
}
Help is highly appreciated.
I have been banging my head with this for days now.
Wesley
You use the prefix parameter to specify common parameters for your grouped routes. So You need one more parameter $lang for this controller:
public function post($lang, $blog_id, $blog_title)
{
// Do something
}
With prefix parameter the routes look like these:
/{lang}/blogs
/{lang}/blog/{postId}/{postTitle}

Route User Role Laravel 5.4

I'm very confused on this situation. I have two routes with on resource name.
Route::resource('product', 'Product\AreaManagerProductController');
Route::resource('product', 'Product\SystemAdminProductController');
I need to make it as one because I have a contextual binding.
$this->app->when(AreaManagerProductController::class)
->needs(ProductInterface::class)
->give(AreaManagerProductRepository::class);
$this->app->when(SystemAdminProductController::class)
->needs(ProductInterface::class)
->give(SystemAdminProductRepository::class);
The contextual binding works fine... but I need to change my route like this.
Route::resource('product_area_manager', 'Product\AreaManagerProductController');
Route::resource('product_system_admin', 'Product\SystemAdminProductController');
I created ProductController and some kind of weird solution.
public function index(){
//Create a conditional statement base on user
return app('App\Http\Controllers\Product\AreaManagerProductController')->index();
}
It may work but it doesn't trigger the middleware... What could be the best practice on this situation. TY
You can have your Route like this
Route::group(['prefix' => 'product', 'namespace' => 'Product', 'middleware' => '<your middleware>'], function() {
Route::resource('area_manager', 'AreaManagerController');
Route::resource('system_admin', 'SystemAdminController');
});
The reason I grouped the route is to reduce redundancy, and the reason i removed Product from the controller name is, as there is a namespace Product already, there is no need of long Class names.
If you wan to access some methods in the AreaManagerController and SystemAdminController just extend the ProductController to these Controllers.
If you want to add some specific middleware for the actions inside these controllers, I have added a middleware clause in the route group which will affect to these controllers, if not needed just remove it.
Hope this helps you.

Laravel 5: Sessions not working the way they should

On top of every controller and routes.php I used:
use Illuminate\Support\Facades\Session;
In routes.php I set the session using:
Session::put('key', 'value');
In a controller I want to call the session value of key using:
echo Session::get('key');
But once I set a new value to key in routes.php and call it in a controller, I still get the first value and not the new one. If I echo the the session using Session::all() in routes.php after setting it, I see the new value, but in a controller it flips back to the first value. I even tried using below in routes.php before setting the new value, but without success.
Session::forget('key');
Am I forgetting something here?
Using regular PHP $_SESSION my routes.php looks like this:
$slug = $_SERVER['REQUEST_URI'];
$slug = explode('/', $slug[0]);
if(in_array($slug[1], Language::all()->lists('iso'))) {
$_SESSION['language'] = $slug[1];
if(!$slug[2]) {
$_SESSION['slug'] = 'home';
Route::any('/{slug}', ['as' => 'pages.page', 'uses' => 'PagesController#page']);
} else {
if($slug[2] != 'dashboard' && $slug[2] != 'migrate' && $slug[2] != 'form-send') {
if (in_array($slug[2], ElementValue::where('element_field_id', 2)->lists('value_char')) && !isset($slug[3])) {
$_SESSION['slug'] = $slug[2];
Route::any('/{slug}', ['as' => 'pages.page', 'uses' => 'PagesController#page']);
} else {
$_SESSION['slug'] = 'home';
Route::any('/{slug}', ['as' => 'pages.page', 'uses' => 'PagesController#page']);
}
}
}
}
Where in routes.php are you setting the session value? It sounds like you're doing something like this:
Session::put('key', 'value');
Route::get('my-route', 'MyController#doSomething');
and then doing this:
class MyController {
public function doSomething()
{
Session::get('key');
}
}
Is that correct? If so, read on...
I'm no expert on the Laravel request lifecycle (for more, see the documentation), but it doesn't surprise me that this doesn't work. The way I think about it is this: the routes.php file is loaded and executed early in the life cycle - probably first - since it tells the application what code to execute next (ie. what do when a particular request is received). And when I say "early in the life cycle", I mean early - like before sessions are initialized. I believe that the Session::put call is simply being ignored, since at the time when you're setting the value, the session does not exist.
You may want expand your question with a little more detail about what you're trying to accomplish - there has got to be a better way to do it.
EDIT - in response to the comments below...
I am not saying you should touch the $_SESSION superglobal - that's a bad idea because I'm not even sure that Laravel uses the native PHP session facility and you have no guarantee that whatever you do will continue to work in the future.
It's not clear what you're trying to do, but to me this sounds like a value that does not belong in the session.
By placing the Session::put in the routes.php file, it sounds like you have some value that's important and should be set for every session and every request
If that's the case, and it's a static value, then it's not a session value, it's a configuration value.
If, instead, it's a dynamic value and/or it changes depending on which user is associated with a session, then you can set it in one of several places:
if you're using controller-based routing, you could set this in the controller constructor, although I wouldn't recommend it, because you will probably have to do it for several controllers, leading to code duplication
if you're using closures in your routes, set it there. E.g.
Route::get('some/route', function () {
Session::put('key', 'value');
// this works, because the closure isn't executed until after
// the application is initialized
});
you could also do it in middleware
or in a service provider (although I'm not certain that sessions would be available when the service providers are executed).
The best option is probably middleware - this would allow you to set (or calculate) the session value in one place in your code and also associate it with particular routes, if you don't need it for all routes.
Don't use $_SESSION in laravel. Uses the laravel Session class. See the following post How to access the globals $_SESSION and $_COOKIE from a laravel app?
Also, all your if logic should not be living in routes.php. You should add that to middleware to filter your routes.
Also, you are really making this hard for yourself. Laravel provides most of what you need in convenient helper classes e.g. Request::url(), Request::getHost(), Request::getLocale(). Have a read through the docs and get familiar with "The Laravel Way" it will be much easier and things will then work as you expect.
I moved the logic to the controller and now my routes are this simple:
Route::pattern('slug', '[a-zA-Z0-9\-_\/]+');
$slug = Request::path();
if(isset($slug)) {
Route::any('/{slug}', 'PagesController#index')->where('slug', '[a-zA-Z0-9\-_\/]+');
}
The session is stored in the PagesController and used further in the application. Thanks for your help guys.

Resources