Dynamic Slugs in multilingue website Laravel 4 - laravel-4

I have a multilingue website created using Laravel 4, and I have lot of pages such as : "policy, "terms", "how it works" in database, so to access thoses pages I use this route:
// Group by locale
Route::group(
array( 'prefix' => $locale ), function () {
Route::get('{slug}', array('uses' => 'PageController#show','as' => 'pages.show');
// Website routes
});
And then I search for the given slug and the current locale.
My is problem is that I can't add for example a page link in the footer because the slug is dynamic. so is there any solution to resolve that.
It's make a sense ?
Thanks

You are already catching the slug in
Route::get('{slug}', array('uses' => 'PageController#show','as' => 'pages.show');
part. all you need is to inject this slug into controller like this:
class PageController extends BaseController {
public function show($slug)
{
return 'showing slug ' . $slug;
}
}
and whatever value the route receive for {slug} part in route laravel will automatically inject that value into the controller.

Related

Dynamic url routing in Laravel

I am new in Laravel using version 5.8
I do not want to set route manually for every controller.
What i want is that if i give any url for example -
www.example.com/product/product/add/1/2/3
www.example.com/customer/customer/edit/1/2
www.example.com/category/category/view/1
for the above example url i want that url should be treated like
www.example.com/directoryname/controllername/methodname/can have any number of parameter
I have lots of controller in my project so i want this pattern should be automatically identified by route and i do not need to specify manually again and again Directory Name, Controller , method and number of arguments(parameter) in route.
try this:
Route::get('/product/edit/{id}',[
'uses' => 'productController#edit',
'as'=>'product.edit'
]);
Route::get('/products',[
'uses' => 'productController#index',
'as'=>'products'
]);
in the controller:
public function edit($id)
{
$product=Product::find($id);
return view('edit')->with('product',$product);
}
public function index()
{
$products=Product::all();
return view('index')->with('products',$products);
}
in the index view
#foreach($products as $product)
Edit
#endforeach
in the edit view
<p>$product->name</p>
<p>$product->price</p>

Laravel Redirect url from {id} to {id}/{name}

I am new in laravel framework now I'm working fully developed website using Laravel. I have changed blog url form {id} to {id}/{name} like www.example.com/news/203 to www.example.com/news/203/title. It's working fine. but i need to redirect if old url enter into current url opened from cache or something else.
Route::get('{id}/{name}', 'EventController#show')
->name('events-detail')
->where([
"id" => "[0-9]+"
]);
You can define another route in which you will find the model by id and use its title to redirect the user to the new route:
Route::get('{id}', function ($id) {
$model = Model::findOrFail($id);
return redirect()->route('events-detail', ['id' => $id, 'name' => $model->name]);
});
Note that you have to change Model with the class you use for this route.
Create 2 routes and add below code.
Route::get('{id}/{name}', function () {
//new URL as you want
return redirect()->route({id}/{name});
});
Route::get('{id}', function () {
//as you want for simple URL
});
I'm assuming the name portion is not really used at all, except for SEO/friendlier urls. If this is the case, just make the name parameter optional, and there will be no need for a redirect:
Route::get('{id}/{name?}', 'EventController#show')
->name('events-detail')
->where([
"id" => "[0-9]+"
]);
This route will match /203 and /203/news-title.

Localization in laravel

I designed a site with Laravel. now I want add new language to it.I read laravel document . It was good but I have a problem.suppose I have a page that show detail of products so I have a route like mysite.com/product/id that get product's id and show it.also I have a method in controller like
public function showProduct($id){
...
}
If I add new Language , the route will change to this: mysite/en/product/id
now I must change my method because now two parameter send my method.something like this :
public function showProduct($lang,$id){
...
}
So two problems arise:
I must change all method in my site which is time consuming
I do not need language parameter in methods because I set $locan via middleware
pay attention that I do not want remove for example en from my URL (because of SEO)
Open your RouteServiceProvider and say that language parameter actually is not a parameter, it's a global prefix.
protected function mapWebRoutes()
{
Route::group([
'middleware' => 'web',
'namespace' => $this->namespace,
'prefix' => Request::segment(1) // but also you need a middleware about that for making controls..
], function ($router) {
require base_path('routes/web.php');
});
}
here is sample language middleware, but it's need to be improve
public function handle($request, Closure $next)
{
$langSegment = $request->segment(1);
// no need for admin side right ?
if ($langSegment === "admin")
return $next($request);
// if it's home page, get language but if it's not supported, then fallback locale gonna run
if (is_null($langSegment)) {
app()->setLocale($request->getPreferredLanguage((config("app.locales"))));
return $next($request);
}
// if first segment is language parameter then go on
if (strlen($langSegment) == 2)
return $next($request);
else
// if it's not, then you may want to add locale language parameter or you may want to abort 404
return redirect(url(config("app.locale") . "/" . implode($request->segments())));
}
So in your controller, or in your routes. you don't have deal with language parameter
Something like
Route::group(['prefix' => 'en'], function () {
App::setLocale('en');
//Same routes pointing to the same methods...
});
Or
Route::group(['prefix' => 'en', 'middleware' => 'yourMiddleware'], function () {
//Same routes pointing to the same methods...
});

How to add dynamically prefix to routes?

In session i set default language code for example de. And now i want that in link i have something like this: www.something.com/de/something.
Problem is that i cant access session in routes. Any suggestion how can i do this?
$langs = Languages::getLangCode();
if (in_array($lang, $langs)) {
Session::put('locale', $lang);
return redirect::back();
}
return;
Route::get('blog/articles', 'StandardUser\UserBlogController#AllArticles');
So i need to pass to route as prefix this locale session.
If you want to generate a link to your routes with the code of the current language, then you need to create routes group with a dynamic prefix like this:
Example in Laravel 5.7:
Route::prefix(app()->getLocale())->group(function () {
Route::get('/', function () {
return route('index');
})->name('index');
Route::get('/post/{id}', function ($id) {
return route('post', ['id' => $id]);
})->name('post');
});
When you use named routes, URLs to route with current language code will be automatically generated.
Example links:
http://website.com/en/
http://website.com/en/post/16
Note: Instead of laravel app()->getLocale() method you can use your own Languages::getLangCode() method.
If you have more questions about this topic then let me know about it.
Maybe
Route::group([
'prefix' => Languages::getLangCode()
], function () {
Route::get('/', ['as' => 'main', 'uses' => 'IndexController#index']);
});

Multiple routes to same Laravel resource controller action

I like to use resource controllers in Laravel, as it makes me think when it comes to data modelling. Up to now I’ve got by, but I’m now working on a website that has a public front-end and a protected back-end (administration area).
I’ve created a route group which adds an “admin” prefix, like so:
Route::group(array('before' => 'auth', 'prefix' => 'admin'), function()
{
Route::resource('article', 'ArticleController');
Route::resource('event', 'EventController');
Route::resource('user', 'UserController');
});
And I can access the methods using the default URL structure, i.e. http://example.com/admin/article/1/edit.
However, I wish to use a different URL structure on the front-end, that doesn’t fit into what resource controllers expect.
For example, to access an article, I’d like to use a URL like: http://example.com/news/2014/06/17/some-article-slug. If this article has an ID of 1, it should (under the hood) go to /article/1/show.
How can I achieve this in Laravel? In there some sort of pre-processing I can do on routes to match dates and slugs to an article ID, and then pass that as a parameter to my resource controller’s show() method?
Re-visiting this, I solved it by using route–model binding and a pattern:
$year = '[12][0-9]{3}';
$month = '0[1-9]|1[012]';
$day = '0[1-9]|[12][0-9]|3[01]';
$slug = '[a-z0-9\-]+';
// Pattern to match date and slug, including spaces
$date_slug = sprintf('(%04d)\/(%02d)\/(%02d)\/(%s)', $year, $month, $day, $slug);
Route::pattern('article_slug', $date_slug);
// Perform the route–model binding
Route::bind('article_slug', function ($slug) {
return Article::findByDateAndSlug($date_slug);
});
// The actual route
Route::get('news/{article_slug}', 'ArticleController#show');
This then injects an Article model instance into my controller action as desired.
One simple solution would be to create one more route for your requirement and do the processing there to link it to the main route. So, for example:
//routes.php
Route::get('/arical/{date}/indentifier/{slug}', array (
'uses' => 'ArticleController#findArticle'
));
//ArticleContoller
public function findArticle($date,$slug){
$article = Article::where('slug','=','something')->first(); //maybe some more processing;
$article_id = $article->id;
/*
Redirect to a new route or load the view accordingly
*/
}
Hope this is useful.
It seems like if Laravel 4 supports (:all) in routing, you would be able to do it with ease, but unfortunately (:all) is not supported in Laravel 4.
However, Laravel 4 allows detecting routes by regular expression, so we can use ->where('slug', '.*').
routes.php: (bottom of the file)
Route::get('{slug}', 'ArticleController#showBySlug')->where('slug', '.*');
Since Laravel will try to match the top most route in routes.php first, we can safely put our wildcard route at the bottom of routes.php so that it is checked only after all other criteria are already evaluated.
ArticleController.php:
class ArticleController extends BaseController
{
public function showBySlug($slug)
{
// Slug lookup. I'm assuming the slug is an attribute in the model.
$article_id = Article::where('slug', '=', $slug)->pluck('id');
// This is the last route, throw standard 404 if slug is not found.
if (!$article_id) {
App::abort(404);
}
// Call the controller's show() method with the found id.
return $this->show($article_id);
}
public function show($id)
{
// Your resource controller's show() code goes here.
}
}
The code above assumes that you store the whole URI as the slug. Of course, you can always tailor showBySlug() to support a more advanced slug checking.
Extra:
You could also do:
Route::get('{category}/{year}/{slug}', 'ArticleController#showBySlug')->where('slug', '.*');
And your showBySlug() would just have additional parameters:
public function showBySlug($category, $year, $slug)
{
// code
}
Obviously you can extend to month and day, or other adaptations.

Resources