How change url adress with id on name in Laravel? - laravel

I have a website on which each user has his own page and has such an address mysite.com/id44, also, each user can make a short name and I want that instead of a id, the address would be mysite.com/username. How can this be realized?

OK. With no code is complicated, but let's try something.
On your controller just say
Route::get('user/{user:username}', 'UserController#show')->name('user.home.page')
This will search for the user using username as the key.
Check out this video on laracasts Jeffrey Way has explained it very well:
https://laracasts.com/series/whats-new-in-laravel-7/episodes/4
Or
https://laravel.com/docs/7.x/routing#implicit-binding
Hope it helps

For Laravel 7+:
as Samuel BiƩ said...
Route::get('user/{user:username}', 'UserController#show');
For Laravel 6-:
add a method in User Model
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'username';
}

You have to use like that in your route
Route::get('/{user?}', 'UserControllerNameController#your_method_name');

Related

routing with model and variable

I am trying to test a custom email verification code with route model binding, when 2 wildcards are used, laravel always returns a 404.
this is my route in api.php
Route::get('/verify_contact_email/{id}/{hashed_key}', 'CustomEmailVerifyController#verifyContactEmail');
this is the controller with verifyContactEmail
public function verifyContactEmail(UserContactEmailVerify $id, $hashed_key) { return $id; }
when I remove the wildcard {hashed_key} and the $hashed_key, the model shows. I read up on laravel routing documentation, there is no mention of multiple wildcards or passing variable thru URL. Am I doing it wrong? Any help is much appreciated.
You should try this
public function verifyContactEmail($id, $hashed_key) {
$id = UserContactEmailVerify::findOrFail($id);
if(isset($id)){
return $id;
}
}
There is no problem with the route model binding or controller functions. The problem was discovered that routes do not work with hashing or bcrypt, str_random(20) has replaced the verification code instead of bcrypt.

How to Hide Required Parameters Laravel Route

So I have a booking system. Basically it has this route
localhost:8080/itpr/booking/details/{$bookingId}
Where $bookingId = is the id in the booking_table.
My question, is there a way to hide the $bookingId from my routes from the the user? I don't want other users to be able to access to other booking transaction just by changing the $bookingId in the URL.
The easiest way to achieve this is by submiting your post request via AJAX. But if you are not comfortable using ajax request. You can create a policy that allows only the owner of those booking to make change: see code below.
php artisan make:policy BookingPolicy --model=Booking
Register the policy in your AuthServiceProvider: use App\Policies\BookingPolicy;
protected $policies = [
Booking::class => BookingPolicy::class,
];
Now inside your BookingPolicy then define policy for any method that you want to restrict users from. For example let make sure onl the authenticated user(owner) can update his booking. In this scenario we are assuming that you have user_id column in your Booking table and you have relationship between these 2 tables
public function update(?User $user, Booking $booking)
{
return $user->id === $booking->user_id;
}
Now in your BookingController you can call implement the authorizing actions(can or cant)
public function update(Request $request, $id) {
if ($user->can('update', $booking)) {
// Executes the "create" method on the relevant policy...
}
}
Hopefully this will help :)
have you considered using $table->uuid('id'); for PK? So that the users are not going to guess other bookings easily.
Add a check in your route if the booking ID is one that belongs to the user trying to access the ID. If not, redirect.
Otherwise, provide a dashboard like route showing the user bookings. then make an asynchronous call on the click using your userID/bookingID send that data to a template with a route that is something like your booking/details
Please Check Laravel Policy and define rules to check if the booking id is associated with the current user or not and . which can help you to secure the booking detail from unauthorized user.

Add extra question to Laravel forgotten password form and custom its error messages

I'd like to customize the forgotten password form in Laravel.
When asking to reset the password, the user will have to answer a simple question (the name your first pet, the name of your childhood best friend, etc) besides inserting his/her email. This is to avoid other people asking password reset if they know the account's email, but are not the owner of the account.
I also would like to custom the errors messages to, actually, not show errors. For example, if an invalid email is inserted, it would not show the error message "We can't find a user with that e-mail address." I don't like it because someone may guess the email of a user by trying different emails until she/he stops getting the error message. Instead, I would like to show the message "If the information provided is correct, you will receive an email with the link to reset your password."
How to add these functionalities to Laravel auth?
I am looking for a solution that I don't have to create an entire login system from scratch (I think that if I try to design everything from scratch I'd probably miss something and create security vulnerabilities). I'd like to keep the Laravel auth system and just add these two features.
Feel free to suggest other ways to achieve the desired result and to make my question clearer. I'll appreciate that.
The good news is you don't need to rewrite everything.
The bad news is, you need to understand traits and how to extend/override them, which can be a little confusing.
The default controller that Laravel creates ForgotPasswordController doesn't do much. Everything it does is in the trait. The trait SendsPasswordResetEmails contains a few methods, most importantly for the validation in validateEmail method.
You can override this validateEmail method with one that checks for an answered question. You override traits by altering the 'use' statement.
For example change;
use SendsPasswordResetEmails
to:
use SendsPasswordResetEmails {
validateEmail as originValidateEmail
}
This will tell the code to re-name the original method validateEmail to originValidateEmail allowing you to create a new validateEmail in your own ForgotPasswordController.
You can then, inside ForgotPasswordController add a replacement which will be called by the default reset password code:
protected function validateEmail(Request $request)
{
// add in your own validation rules, etc.
$request->validate(['email' => 'required|email', 'questionfield' => 'required']);
}
To alter the error message, you can simply edit the language file found in resources/lang/en/passwords.php
Hope that helps.
Thanks to the user #Darryl E. Clarke, I managed to solve the problem. Here is what I did:
Add this line at the top of the file ForgotPasswordController, after namespace:
use App\User;
Add these 3 methods in the same file:
/**
* Send a reset link to the given user.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
public function sendResetLinkEmail(Request $request)
{
$this->validateRequest($request);
// We will send the password reset link to this user. Regardless if that
// worked, we will send the same response. We won't display error messages
// That is because we do not want people guessing the users' email. If we
// send an error message telling that the email is wrong, then a malicious
// person may guess a user' email by trying until he/she stops getting that
// error message.
$user = User::whereEmail($request->email)->first();
if ($user == null) {
return $this->sendResponse();
}
if ($user->secrete_question != $request->secrete_question) {
return $this->sendResponse();
}
$this->broker()->sendResetLink(
$this->credentials($request)
);
return $this->sendResponse();
}
/**
* Validate the given request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateRequest(Request $request)
{
$request->validate(['email' => 'required|email', 'secrete_question' => 'required|string']);
}
/**
* Get the response for a password reset link.
*
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
protected function sendResponse()
{
$response = 'If the information provided is correct, you will receive an email with a link to reset your password.';
return back()->with('status', $response);
}
Customize it the way you want.
Hope that it will helps others!!

Using getAuthPassword() with another Model instead of User Model?

I am facing issue, I want to use different field name for password. let us say in users table, when I use this code with User model it works perfectly
/**
* Override required, otherwise existing Authentication system will not match credentials
* #return mixed
*/
public function getAuthPassword()
{
return $this->userPassword;
}
but when I use it with another Model let us say Customer model with same table structure , it doesnt work??!!! does anyone have idea about this issue
Thanks in advance.
In your config folder there is a file "auth.php" in this file you found authentication driver set to 'model' => 'App\User'
Instead of User you can use any of your model.
Hope this will help you :)

show name instead of id in a url using laravel routing

I have defined a route in laravel 4 that looks like so :
Route::get('/books/{id}', 'HomeController#showBook');
in the url It shows /books/1 for example , now i'm asking is there a way to show the name of the book instead but to keep also the id as a parameter in the route for SEO purposes
thanks in advance
You could also do something like this:
Route::get('books/{name}', function($name){
$url = explode("-", $name);
$id = $url[0];
return "Book #$id";
});
So you can get book by id if you pass an url like: http://website.url/books/1-book-name
if your using laravel 8, this may be helpfull.
In your Controller add this
public function show(Blog $blog)
{
return view('dashboard.Blog.show',compact('blog'));
}
In your web.php add this
Route::get('blog/{blog}', [\App\Http\Controllers\BlogController::class,'show'])->name('show');
Then add this to your model (am using Blog as my Model)
public function getRouteKeyName()
{
return 'title'; // db column name you would like to appear in the url.
}
Note: Please let your column name be unique(good practice).
Result: http://127.0.0.1:8000/blog/HelloWorld .....url for a single blog
So no more http://127.0.0.1:8000/blog/1
You are welcome.
You can add as many parameters to the url as you like, like this:
Route::get('/books/{id}/{name}', 'HomeController#showBook');
Now when you want to create an url to this page you can do the following:
URL::action('HomeController#showBook', ['id' => 1, 'name' => 'My awesome book']);
Update:
If you are certain that there will never be two books with the same title, you can just use the name of the book in the url. You just need to do this:
Route::get('/books/{name}', 'HomeControllers#showBook');
In your showBook function you need to get the book from the database using the name instead of the id. I do strongly encourage to use both the id and the name though because otherwise you can get in trouble because I don't think the book name will always be unique.
You can also use model binding check more on laravel docs
For example
Route::get('book/{book:name}',[BookController::class,'getBook'])->name('book');
The name attribute in "book/{book:name}" should be unique.

Resources