Laravel custom permalink - php

I am trying to change the url of my article page so instead of showing the article id I'd like to show the article title.
Currently the URL is as follows;
https://www.example.com/posts/post/32
Where 32 is just a random article id.
Instead I like it to display as follows;
https://www.example.com/posts/post/my-amazing-article
Now I have looked in the laravel documentation and different posts on stackoverflow and tried a bunch of stuff but I'm obviously making a mistake somewhere cus nothing seems to work so im pretty much back where I started.
Blade
Route
Route::get('/posts/post/{id}', [App\Http\Controllers\WelcomeController::class, 'post'])->name('post');
Controller
public function post(request $request){
$id = $request->id;
$article = Tinymce::find($id);
return view('/post')->with('articles, $articles');
}
Now the articles, which are saved in Tinymce, are actually created on a different controller on subdomain.
public function tinymce(Request $request)
{
if(request()->ajax())
{
if($request->article_id == null)
{
$tinymce = new Tinymce;
}else{
$tinymce = Tinymce::find($request->article_id);
}
$tinymce->description = $request->description;
$tinymce->content = $request->myContent;
$tinymce->title = $request->title;
$tinymce->author = $request->author;
$tinymce->publish = $request->publish;
$title = $tinymce->title;
$slug = Str::slug($title, "-");
$tinymce->slug = $slug;
$tinymce->save();
return $tinymce->id;
}
}
As you can see I've turned the title into a slug as I read somewhere that's the way to go to use custom url but I didn't get very far with it.
Any help would be greatly appreciated, thank you.

Explanation:
First, As you said you stored slug into your database. so, that's good.
From Controller to View, you can get that slug into post object.
Blade View : (you have to pass slug in route url)
Route : (make id to slug)
Route::get('/posts/post/{slug}', [App\Http\Controllers\WelcomeController::class, 'post'])->name('post');
Controller : (now you can get slug from the second parameter)
public function post(request $request, $slug = ''){
$article = Tinymce::where('slug', $slug)->first();
return view('/post', compact('article'));
}
Now, you can use access custom URLs using slug.
I Hope, it helps you. #assiemp

Related

How to prevent get/post clash in Laravel 6?

Currently I'm working on a project where I made it so that when a user types a correct password in form field, it will give them the items from the given section.
The main problem i'm having is that to do this I need to capture the request and therefore the route has to be a post method instead of a get as such:
public function index(Request $request)
{
$id = $request->input('id');
$password = $request->input('password');
$result = DB::table('scrumboards')->find($id);
if ($result->key == $password) {
$scrumboard = $result;
$items = DB::table('backlogs')->get();
return view('scrumboard', ['items' => $items, 'scrumboard' => $scrumboard]);
} else {
$scrumboard = $result;
return redirect('home');
}
}
and the route as such:
Route::post('/scrumboard', 'ScrumboardController#index');
By doing this, request errors wont work since It wants to redirect back but can't since this is a post method.
Any way I can avoid this clash?
Routes can have multiple HTTP verbs. Define your route as
Route::match(['get', 'post'], '/scrumboard', 'ScrumboardController#index');
to make it available as GET and POST route.

Laravel - Prevent extra characters slug parameters

I have multiple routes with route model binding that direct users from Shop > Category > Product. The route links are working fine.
But if a user adds a garbage value to the URL, Laravel does not throw 404 error. How can force 404 error if a user adds any extra character to URL?
Route
Route::get('/{shop_url}/{category_url}/{product_url}/buy', 'Controller#buy')->name('buy')->where(['shop_url', 'category_url', 'product_url' => '[\w\d\-]+(.*)']);
Route::get('/{shop_url}/{category_url}', 'Controller#view')->name('view')->where(['shop_url','category_url' => '[\w\d\-]+(.*)']);
Route::get('/{shop_url}', 'Controller#shop')->name('shop')->where('shop_url', '[\w\d\-]+(.*)');
Controller
public function shop($shop_url)
{
$shop = Shop::where('shop_url', $shop_url)->firstorfail();
return view ('shop', compact('shop'));
}
public function view($shop_url, $category_url)
{
$shop = Shop::where('shop_url', $shop_url)->firstorfail();
$category= Category::firstorfail();
return view ('shop', compact('shop', 'category'));
}
public function buy($shop_url, $category_url, $product_url)
{
$shop = Shop::where('shop_url', $shop_url)->firstorfail();
$category= Category::where('category_url', $category_url)->firstorfail();
$product = Product::firstorfail();
return view ('shop', compact('shop', 'category', 'product'));
}
Here domain.com/shop-ca/clothing works and if user types domain.com/shop-ca/clothes, it also displays the same page. Here I want it to display 404. How would I do that?
First of all, you should check your slug, in your code I see these lines:
$category= Category::firstorfail();// it will get the first route in the database, not the needed category
So, first, try to do this:
public function view($shop_url, $category_url)
{
$shop = Shop::where('shop_url', $shop_url)->firstOrfail();
$category= Category::where('category_url', $category_url)->firstOrfail();// I actually don't know the name of your slug field, but if the category is wrong, laravel will return 404 page.
return view ('shop', compact('shop', 'category'));
}
You have check $product_url in your buy function and through 404 error manually.

Sending POST request with GET parameter in Laravel

For example, I have this route in my web.php :-
Route::get('products/{product}/owners', 'ProductController#showOwners');
When I try to add new 'Owner' to the product, I have to do it in the parent URL, like this :-
Route::post('products/storeOwner', 'ProductController#storeOwner');
And then I pass the product ID in a hidden field in the form, because the post request doesn't accept URL parameters. So is there anyway to do it like below ?
Route::post('products/{product}/storeOwner', 'ProductController#storeOwner');
So the POST request will be sent inside the particular 'product' URL?
UPDATE
/* ProductController Class */
public function storeOwner (AddProductOwner $request)
{
$product= Product::find($request->product);
$user = Auth::user();
if ( $user->ownerOf($product)) {
// Check if the current user is already one of the owners).
// If the current user is the owner then return to the product
// This line is not executed because in (products/show.blade.php) we have set a condition.
return redirect('products/' . $request->product);
}
$join = new Join;
$join->role = $request->join_role;
$join->product()->associate($request->product);
$join->user()->associate(Auth::user());
$join->message = $request->message;
$join->save();
// TODO: we have to make this with ajax instead of normal form
return redirect('products/'. $request->product);
}
I hope my question is clear enough..
Yes you can do as you mentioned in your last route
Route::post('products/{product}/storeOwner', 'ProductController#storeOwner');
And then get the product Id in your functions argument
public function storeOwner (AddProductOwner $request, $productId)
{
dd($productId); // TRY THIS OUT. CHECK THE 2nd ARGUMENT I SET.
$product= Product::find($productId); // PASS THE VERIABLE HERE.
$user = Auth::user();
if ( $user->ownerOf($product)) {
// Check if the current user is already one of the owners).
// If the current user is the owner then return to the product
// This line is not executed because in (products/show.blade.php) we have set a condition.
return redirect('products/' . $request->product);
}
$join = new Join;
$join->role = $request->join_role;
$join->product()->associate($request->product);
$join->user()->associate(Auth::user());
$join->message = $request->message;
$join->save();
// TODO: we have to make this with ajax instead of normal form
return redirect('products/'. $request->product);
}
You can send URL parameters to a POST request. Just make sure in your form you are sending the wildcard.
<form action="/products/{{ $productid }}/storeOwner" method="POST">
In your routes
Route::post('products/{productid}/storeOwner', 'ProductController#storeOwner');
In your controller, use it
public function storeOwner($productid)
{
dd($productid);
}

Is it possible to load a view that requires a user id, without determining it in the URI in Laravel 5.1

I'm continuing my adventure with Laravel 5.1. I have a small project I'm working on and I'm looking to find a nice way to load a User's gecko ideally without having the user id in the URI.
This is my current URI which works as it is:
Route::get('gecko/{user_id}/{name}', 'GeckoController#show');
As you can see i'm holding the user id in the URI and then i'm querying it to find the right gecko. As shown below:
public function show($user_id, $name)
{
$name = str_replace('-', ' ', $name);
$gecko = Gecko::where(compact('user_id', 'name'))->first();
return view('gecko.show', compact('gecko'));
}
So to get this to work, I would do project.dev/gecko/1/Zilly - It works, but having the User ID in there kind of sucks. I decided that having the User ID was important in case there were multiple users who have geckos with the same name.
Any help on this is greatly appreciated, and if you need any extra code let me know :)
Andy
If you would like to use username instead of user_id:
Routes:
Route::get('gecko/{username}/{geckoname}', 'GeckoController#show');
Controller:
public function show($username, $geckoname) {
$user_id = User::where('username', $username)->first()->id;
$geckoname = str_replace('-', ' ', $geckoname);
$gecko = Gecko::where(compact('user_id', 'geckoname'))->first();
return view('gecko.show', compact('gecko'));
}
If the user authenticated you can use Auth::user()->id and you should add only the gecko id.
For example:
Routes:
Route::get('gecko/{gecko_id}', 'GeckoController#show');
Controller:
public function show($id) {
$gecko = Gecko::find($id)->where('user_id', Auth::user()->id)->first();
return view('gecko.show', compact('gecko'));
}
If you would like to use geckoname:
Routes:
Route::get('gecko/{geckoname}', 'GeckoController#show');
Controller:
public function show($geckoname) {
$gecko_id= Gecko::where('geckoname',$geckoname)->first()->id;
$gecko = Gecko::find($gecko_id)->where('user_id', Auth::user()->id)->first();
return view('gecko.show', compact('gecko'));
}

Replace ID from CakePHP URL

How can I replace the /posts/view/id with /posts/view/code ?
code is a field in the database that contains 10 random numbers generated using mt_rand() function.
In the PostsController I have this function for viewing posts:
public function view($id = null) {
$this->Post->id = $id;
$this->set('post', $this->Post->read());
}
Now I want to use code instead of id.
Thank you for your answers!
UPDATE:::
Someone from the CakePHP Q&A solved my problem.
I'll put the codes here so if someone needs the same solution, it can be found here.
in your routes.php add this code:
Router::connect('/posts/view/:code', array('controller' => 'news', 'action' => 'view'), array('pass' => array('code')));
in your controller change the view method like this:
public function view($code = null) {
$this->set('post', $this->Post->findByCode($code));
}
Thank you so much!
i used cakePHP
just few times, but i think you should see routing in cakePHP, you should change rewrite of url
I think that would be a URL like /posts/view/id/code. Then using the ID, you grab the code from the database:
public function view($id = null, $code = null) {
$this->Post->id = $id;
//..DO CAKEPHP QUERY TO GET CODE USING ID HERE. ASSIGN TO $code.
$this->Post->code = $code;
$this->set('post', $this->Post->read());
}

Categories