How to Pass slugged url to Controller in Laravel - php

Hey Guys I am new to Laravel and I am currently trying to pass a slugged url into my controller, but I am having issues with it.
I have a table for categories and I have all the categories looped through and displayed on a view page (/posts). I listed all the categories on this view, so that when a user clicks on a category, they will be taken to a different page showing all posts belonging to that category(e.g, /posts/category/{categoryID}). I know I can get this done by passing the category id to the controller and finding the id to pass back to that view. However, I am trying to do something different.
I am looking to pass the category name instead of the id to the controller. E.g, /posts/category/{category name}. But due to the fact that some categories are more than a word (e.g, Dry Cleaning), it has become a challenge for me. I had earlier slugged the URL for SEO purpose (e.g, /posts/category/{Str::str(categoryname)}) and from the web.php file, I created a get route.
Now, I'd like to fetch all posts relating to the category name passed in. The issue is that the category names are slugged.
Is there a way to remove the slug("-" or hyphen) from the name passed into the controller? So, instead of "Dry-cleaning", it will come back as "Dry cleaning" which matches the name in the database.
I am trying to avoid passing id to the url.
Thanks.

Good question.
There are a couple of approaches you can use to tackle this problem. I'll run through them for you.
1. Store the slug in the database
One option is to store the slug name within the database. Personally this is my favourite option as you don't need to do any string transformations. With this approach I would put a slug column in your categories table. Then you can use the Category eloquent model to search for a category with that slug.
2. Convert the slug to title case
The second option is to convert the slug to title case. You can do this by using Laravel's string class. For example:
$categoryName = Str::title($slug);
However there are a few issues with this approach. Firstly, when creating a slug the url will remove characters that are not safe, for example an apostrophe. This means if you have a pluralised category name it won't match when converting the slug back to title case.
Secondly, by using code to transform strings in order to match a record in the database you are at the mercy of the service class. While the functionality of Str::title is unlikely to change, it could in theory which could then mean you have to change code later on down the line.
Conclusion
Overall, I would recommend going with the first approach. You have much better data integrity and less chance of things going wrong further down the line. So if I were you I would create a new migration to add a slug column to your categories table and then populate each category with its own slug. Then search for a category based on the slug column when querying your eloquent model.

Related

Is there any way to change url in Laravel 5.5?

I am developing a site with Laravel 5.5
I am going to hide the product slug when customers visit single product page.
original url: http://localhost/laravel/product/category-name-product-slug (this is product slug in database)
must be changed to: http://localhost/laravel/product/category-name.php (or html)
The problem is that I have to send the product-slug to controller so that know about what product is needed instead of product ID.
Also I have to show category name(this must be substring of product-slug: substr($product_name, 0, -10)) on browser url.
How can I solve this problem?
If you can't put it in the path you'll have to use a query string.
Retrieving Input From The Query String
e.g. http://localhost/laravel/product/category-name.php?product-slug=product-slug
and if you have to do that you might not lose any seo by also passing the category and product ids in the query string.
I have solved this problem by using form.
I have created a form in blade and made its method to POST.
Defined a hidden variable to represents product slug, and then render a virtual slug name (substring of product slug) to route.

How to query listings in Sabai Directory plugin?

I'm looking for a way to query listings in PHP using Sabai Directory plugin. In my code, I extract the keywords from $_SERVER['REQUEST_URI'] and then intend to use them to find matching listings. Now, the problem is I need a way to assign those keywords to my listings in the first place. I tried 2 approaches:
Categories. It seems that Sabai does not support core WP categories (does it?), but has its own version. So if you create a Category, Sabai creates a page with a permalink for it. However, my categories are very trivial, they just have a label and a value with no content or no media; I don't want users to see category pages (e.g. /directory/categories/chocolate), it makes no sense.
Is there a way NOT to create a separate page for each category?
How do you query listings by multiple categories? Would this work: [sabai-directory category="chocolate,arizona,phoenix"], with category separated by comma?
Custom fields. I couldn't figure out categories by myself, so I created custom fields to simulate core WP categories. But the problem is I can't find a way to query listings by these custom fields. So if I need field_state field to be set to arizona or massachusetts, how do I limit my listings to either of those values?
Is there a way to specify custom fields in shortcodes?
Is there an API in Sabai that I can use to query listings directly? What would the post type be? What would the query look like? (There is no info on this in the docs)
On the same topic, once you query the listings, how do you display the contents for a single listing? I've tried [sabai-directory-listing id="?"] shortcode, but I don't understand where you get the id from: $post->id doesn't work.
Please let me know if you have any info

Subcategories and resource controllers?

Im using a resource controller to control articles.
/news
Hits the index method and brings up all the articles under the category.
/news/article-slug
Hits the show method and brings up an article under the category.
My question involves sub categories.
/news/sub-category-name
This would hit the show method which would look for an article with the sub-category-name when I want it to hit the index method and bring up a list of articles for the sub category.
What would be the approach to use for sub categories?
Add another route and method like:
get('/news/{subcategory}', [
'as'=>'subcategory',
'uses'=>'ArticleController#getSubCategory',
]);
Or would it be better practice to scrap sub categories and have a url like:
/news-sub-category-name/article-slug
Or is there another way?
Thinking semantics you would be better to servers category names then the title. ie
www.domain.com/news/category/article
This will also give you a clean approach for your routes file. IE no wildcard matching or regex to replace (cat-) etc.
Thats the way I would personally go.
It use to be in the past you would want to keep your URL's as short as possible but thats just not the case these days. Dont get me wrong thats not to say you want domain/cat/cat/cat.....
... Update
To use resources you would have something like.
Route::resource('news/{cat}/article', 'ArticleController');

Laravel 4 - Overriding cviebrock/eloquent-sluggable when build_from and slug are different

I'm trying to set up a sluggable item in the database using cviebrock/eloquent-sluggable in Laravel 4. Its great when you want to force a title to adhere to a slug, but when it comes to making alterations I'm not sure what is the best way to approach it...
Imagine that someone creates a Post with a title "This is my post", sluggable converts it to "this-is-my-post" and does checks to ensure theres no duplicates in the table, or appends a "-1, -2" etc. this is great... however what I want is to do is add an optional form input called slug where a user can override the "build_from" variable in the Model, but retain checks on the override to ensure there are no duplicates.
So a title "This is my post", with a slug of 'foo-bar' should make it retain the slug, but at the moment when I save it reverts back to "this-is-my-post".
Is it possible to bypass build_from in eloquent-sluggable? At the moment even if I change "Slug" it still generates from "Title".
Appreciate any help, and thank you.

How to create dynamic URL for blog in CodeIgniter

I am new to CodeIgniter and I am creating a personal blog. I have done the UI part and I am displaying 260 chars from the article-content.
Where I'm stuck:
When the user click on the article's title, it should go to the page with the URL (E.g.: example.com/title-one). But, I don't know how to fetch the corresponding Content of that title. Both title and content are in the same table coupled with ID.
How can I pass the ID and use that to fetch Content?
When you are creating a post, you can add a field for your slug. Some varchar column would fit. Every slug has to be unique, so you can find the article in your database.
For creating slugs with CI, I would recommend this:
In the url helper you have a method called url_title. Just pass the articles title:
$slug = url_title($title, '_', TRUE);
Then save it with your additional data to the database.
When you are viewing an article. Do something like this:
$slug = $this->uri->segment(n);//change it to fit;
In your fetching model method for viewing an article, just find the article by the given slug.
$this->db->get_where('your_articles_table', array('slug' => $slug));
Also you can add some additional routing, to perfectly fit your needs.

Categories