I use laravel 7 and store following tree structures in database:
Catalogs table:
category1
--category11
--category12
----category121
----category122
--category13
Articles table:
news
--news1
--news2
Вasic Laravel routes looks like:
Route::get('category/{id}', 'categoryController#show');
Route::get('news/{id}', 'newsController#show');
But in this case "category" url's segment is necessary for each catalog's URL and
"news" url's segment is necessary for each new's URL
How can I route the following urls with Laravel Routes:
http://sitename.com/category1
http://sitename.com/category1/category11
http://sitename.com/category1/category12/category121
http://sitename.com/news
http://sitename.com/news/news1
?
You would need a “catch-all” route (registered after all of your other routes if you want all of the path to be configurable).
You could then explode the path on slashes, check each element is a valid category slug and is also a child of the previous category.
// All other routes...
Route::get('/{category_path}', 'CategoryController#show')->where('category_path', '.*');
You could also do this with a custom route binding:
Route::bind('category_path', function ($path) {
$slugs = explode('/', $path);
// Look up all categories and key by slug for easy look-up
$categories = Category::whereIn('slug', $slugs)->get()->keyBy('slug');
$parent = null;
foreach ($slugs as $slug) {
$category = $categories->get($slug);
// Category with slug does not exist
if (! $category) {
throw (new ModelNotFoundException)->setModel(Category::class);
}
// Check this category is child of previous category
if ($parent && $category->parent_id != $parent->getKey()) {
// Throw 404 if this category is not child of previous one
abort(404);
}
// Set $parent to this category for next iteration in loop
$parent = $category;
}
// All categories exist and are in correct hierarchy
// Return last category as route binding
return $category;
});
Your category controller would then receive the last category in the path:
class CategoryController extends Controller
{
public function show(Category $category)
{
// Given a URI like /clothing/shoes,
// $category would be the one with slug = shoes
}
}
Related
hide id from url
https://wallpaperaccess.in/photo/162/download-wallpaper
i want url like this
https://wallpaperaccess.in/photo/download-wallpaper
ImagesController.php
public function show($id, $slug = null ) {
$response = Images::findOrFail($id);
$uri = $this->request->path();
if( str_slug( $response->title ) == '' ) {
$slugUrl = '';
} else {
$slugUrl = '/'.str_slug( $response->title );
}
$url_image = 'photo/'.$response->id.$slugUrl;
//<<<-- * Redirect the user real page * -->>>
$uriImage = $this->request->path();
$uriCanonical = $url_image;
if( $uriImage != $uriCanonical ) {
return redirect($uriCanonical);
}
Route
// Photo Details
Route::get('photo/{id}/{slug?}','ImagesController#show');
NOTE: i don't have any slug column in database, so can we use title as slug?
You should add a column field slug and auto-generate it from title
use Illuminate\Support\Str;
$slug = Str::slug($request->input('title'), '-');
In Models\Image.php
public function getRouteKeyName()
{
return 'slug';
}
In routes\web.php
Route::get('photo/{image:slug}','ImagesController#show');
In app\Http\Controllers\ImagesController.php
use app\Models\Image.php;
...
public function show(Image $image)
{
// controller will automatically find $image with slug in url
// $image_id = $image->id;
return view('your.view', ['image' => $image]);
}
In order to use a slug in the URL instead of an id, you'll need to...
Create a column in your table where you store the slug. A good way to make a slug unique is to append the actual id at the end. If you really don't want to see the id anywhere, you have no choice, you'll have to ensure the slug is unique yourself (there are a lot of ways to achieve this).
This is one way to automatically create an unique slug:
Make sure the slug column is nullable, then open your model and add these methods.
They are called "model events".
created is called when the model is, well, created.
updating is called when you are updating the model but before it's actually updated.
Using created and updating should automatically create the slug when you create or update a Images instance.
protected static function booted()
{
parent::booted();
static::created(function (Images $images) {
$images->slug = Str::slug($images->title.'-'.$images->id);
$images->save();
});
static::updating(function (Images $images) {
$images->slug = Str::slug($images->title.'-'.$images->id);
});
}
From a SEO point of view, updating the slug when the title change is arguably not a good practice, so you might want to omit this part (static::updating...), it's up to you.
Go to your model and add the following method:
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'slug'; //or whatever you call the slug column
}
This way, the router will resolve your model by the slug, not the id.
In your route file, remove the id and change the name of the slug to match the name of your model:
Route::get('photo/{images}','ImagesController#show'); //here I'm assuming your model is Images from what I see in your controller
In your controller, change the declaration of your show method to this:
public function show(Images $images)
{
dd($images);
// if you did all this correctly, $images should be the Images corresponding to the slug in the url.
// if you did something wrong, $images will be an empty Images instance
//
//
// your code...
}
Images should be renamed to Image, models should not be plural. However, it should not make any difference here.
I'm working on my application using Laravel 7, I have done the blog section in my front-end and everything is working well except that I would like to display the URL having name of the category followed by the slug (name of the blog) For example in my URL I would like to have:
www.domain.com/plumbing/best-plumbing-tips-for-your-home instead of www.domain.com/post/best-plumbing-tips-for-your-home
In the second link, "post" is the URL in my web routes file.
"plumbing" is the category "best-plumbing-tips-for-your-home" is the title of the blog and I would like the URL to dynamically pick the name of the Category where the blog post belongs to. Please help.
In my Controller:
public function post($slug){
$post = Post::with('category', 'user')->where('slug', $slug)->first();
$posts = Post::with('category', 'user')->inRandomOrder()->limit(3)->get();
$categories = BlogCategory::all();
if($post){
return view('blog.front-end.post', compact(['post', 'posts', 'categories']));
}else {
return redirect('/');
}
}
public function category($slug){
$category = BlogCategory::where('slug', $slug)->first();
if($category){
$posts = Post::with('category', 'user')->where('category_id', $category->id)->get();
return view('blog.front-end.category', compact(['category', 'posts']));
}else {
return redirect()->route('front-end.home');
}
}
In my Web Routes file:
Route::get('/post/{slug}', 'Blog\FrontEndController#post')->name('front-end.post');
Route::get('/category/{slug}', 'Blog\FrontEndController#category')->name('front-end.category');
Route::get('/blog', 'Blog\FrontEndController#postsForBlogPage')->name('front-end.blog-page');
I am trying to pass variable.
I want to show all the sponsor ids from the id. i.e. if 203035051 passed in the URL then in the view i can see all ids for which 203035051 is sponsor.
Here is my anchor link:
<a href="<?=base_url('v3/member_income?id='.$id);?>">
Here is my Model: MemberIncome
public function display_records($id)
{
$this->db->select('*');
$this->db->from('users');
$this->db->where("id",$id);
$query = $this->db->get();
if ($query) {
return $query->row_array();
} else {
return false;
}
}
Here is my Controller
public function displaydata()
{
/*load Model*/
$this->load->model('MemberIncome');
$result['data']=$this->MemberIncome->display_records($id);
$this->load->view('customer/member_income', $result);
}
here is my route
$route['v3/member_income'] = 'IncomeData/displaydata';
Here the reason:
$route['v3/member_income'] = 'IncomeData/displaydata';
You need to send the ID through routes. Add the (:any) and $1 those are the parameters you need to send. Without it, the "displaydata" won't receive the ID.
$route['v3/member_income/(:any)'] = 'IncomeData/displaydata/$1';
In the anchor section, actually you don't need "?id=", just send it like this
<a href="<?= base_url('v3/member_income/'.$id); ?>">
Missing something in route to catch your ID. Try this way
$route['v3/member_income/(:any)'] = 'IncomeData/displaydata/$1';
I would like to recover the slug of 2 categories from my routes but can’t write the Controller.
My Route
Route::get('technicians/o/{occupation}/c/{city}', 'User\TechnicianController#viewoccupationcity');
My Controller
public function viewoccupationcity($slug)
{
$technicians = TechnicianResource::collection(occupation::where('slug',$slug)->firstOrFail()->technicians()
->with('city','occupation')
->latest()->get());
return $technicians;
}
Route::get('technicians/o/{occupation}/c/{city}', 'User\TechnicianController#viewoccupationcity');
Your controller will accept the parameters from your route as variables by order
public function viewoccupationcity($ocupation, $city)
{
...
}
Example:
URL: technicians/o/foo/c/bar
public function viewoccupationcity($ocupation, $city)
{
// $ocupation will be 'foo'
// $city will be 'bar
}
Ok, you would need to retrieve 2 variables as that is what you are passing
public function viewoccupationcity($occupation, $city)
If you want the whole slug to do another search then you would use the $request object. So like so
public function viewoccupationcity(Request $request, $occupation, $city){ // You also need to include the Request decleration
$slug = $request->path();
$technicians = TechnicianResource::collection(occupation::where('slug',$slug)->firstOrFail()->technicians()
->with('city','occupation')
->latest()->get());
return $technicians;
}
EDIT: We are having to do a lot of guesswork as your question isn't very clear. I think what you are trying to achieve is probably this
public function viewoccupationcity($occupation, $city){
$technicians = TechnicianResource::collection(occupation::where('city',$city)->where('occupation',$occupation)->firstOrFail()->technicians()
->with('city','occupation')
->latest()->get());
return $technicians;
}
If you need something more then you need to give more details
I am working in Codeigniter and I want to hide ID from URL.
my current URL is:
www.localhost/CI/services/1/ac_repair
but need this type of URL in codeigniter:
www.localhost/CI/services/ac_repair
View Page Code:
<?=anchor('services/' . $ser->s_id . '/' . url_title($ser->s_title,'_') ,'View Service');?>
Controller Code:
public function services()
{
$this->load->model('ServicesModel', 'ser_model');
$s_id = $this->uri->segment(2, 0);
if($s_id){
$get_service = $this->ser_model->get_ser($s_id);
return $this->load->view('public/detail', compact('get_service') );
}
else
{
// $services = $this->articles->articles_list( $config['per_page'], $this->uri->segment(3) );
$get_services['result'] = $this->ser_model->all_services_list();
// $this->load->view('public/services', ['services'=>$services]);
$this->load->view('public/services', $get_services);
}
}
Model Code here:
public function get_ser($id)
{
// $q = $this->db
$q = $this->db->select('*')
->from('services')
->where( ['s_id' => $id] )
->get();
if ( $q->num_rows() )
return $q->row();
return false;
}
but need this type of URL in codeigniter:
www.localhost/CI/services/ac_repair
If you want this functionality you have to be able to use your title ac_repair in place of the id. This means the title needs to be marked as unique and therefore not contain any duplicates.
The following pseudo-code should give you an idea:
function services($url_title = null) {
if (!is_null($url_title)) {
// get ser would use title instead of $id
$this->db->where('title', $url_title);
} else {
// all rows
}
}
Other methods would be "hacky" and I cannot think of any off the top of my head that I would consider usable.
Side note: you should never be returning in a view