This question already has answers here:
Laravel: Validation unique on update
(33 answers)
Closed 10 months ago.
I'm going to edit a row using form request validate laravel, but when editing if I do not change the email, The email has already been taken error. Gives
this is from request validate EditAdmin
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules;
use Illuminate\Validation\Rule;
class EditAdmin extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => ['required', 'string'],
'email' => ['required', 'string', 'email', Rule::unique('admins')],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
];
}
}
this my controller AdminController
<?php
namespace App\Http\Controllers;
use App\Repositories\AdminRepository;
use App\Http\Requests\CreateAdmin;
use App\Interfaces\AdminInterface;
use App\Http\Requests\EditAdmin;
use Illuminate\Validation\Rules;
use Illuminate\Validation\Rule;
use Illuminate\Http\Request;
use App\Models\Admin;
class AdminController extends Controller
{
/**
* admin Service Interface
* #var AdminRepository
*/
protected $admin;
/**
* Inject service By Service Container
* #param AdminRepository $admin
*/
public function __construct(AdminRepository $admin)
{
$this->admin = $admin;
}
/**
* Show All Admins
* Method:get
* Return get All admin
* #return \Illuminate\Contracts\View\View
*/
public function getAllAdmin():\Illuminate\Contracts\View\View
{
$admins = $this->admin->getAllAdmin();
return view('admin.list',['admins'=>$admins]);
}
/**
* param:Admin_id
* method delete
* Delete admin
* #param int $id
* #return \Illuminate\Http\RedirectResponse
*/
public function deleteAdmin(int $id):\Illuminate\Http\RedirectResponse
{
$this->admin->deleteAdmin($id);
return redirect('/admins');
}
/**
* get single admin
* method get
* #param $id
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
*/
public function getAdmin(int $id):\Illuminate\Contracts\View\View
{
$admin = $this->admin->getAdmin($id);
return view('admin.edit',['admin'=>$admin]);
}
/**
* Updated Admin
* Route:Api/Nft/$nft_id
* Method:Put
* #param Request $request
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function editAdmin(EditAdmin $request):\Illuminate\Http\RedirectResponse
{
$request->validated();
//validate all input
// $request->validate([
// 'name' => ['required', 'string'],
// 'email' => ['required', 'string', 'email', Rule::unique('admins')->ignore($request->id),],
// 'password' => ['required', 'confirmed', Rules\Password::defaults()],
// ]);
$data = $request->all();
$this->admin->editAdmin($data);
return redirect('/admins');
}
/**
* create new admin
* #param CreateAdmin $request
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function createAdmin(CreateAdmin $request):\Illuminate\Http\RedirectResponse
{
$request->validated();
$data = $request->all();
$this->admin->createAdmin($data);
return redirect('/admins');
}
}
How can I fix this bug?
pleas help me!!!
this is because of using same validator for crate and update user . and user own email in update process make trouble for you .
solotion:
1- crate new validator class for edit user << UserEditRequest >>
2- use this code for validate email
'email' => ['required', 'string', 'email,'.auth()->user()->id,]
Related
I have created laravel api for angular application to register user this is the Registration code and it is working but i want to verify user email after user is registered. I have used laravel default laravel verification in web but i don't have idea of using it in api.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use Illuminate\Auth\Events\Verified;
use Validator;
class AuthController extends Controller
{
public function __construct() {
$this->middleware('auth:api', ['except' => ['login', 'register']]);
}
/**
* Get a JWT via given credentials.
*
* #return \Illuminate\Http\JsonResponse
*/
public function login(Request $request){
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required|string|min:6',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
if (! $token = auth()->attempt($validator->validated())) {
return response()->json(['error_message' => 'Invalid Credentials'], 401);
}
return $this->createNewToken($token);
}
/**
* Register a User.
*
* #return \Illuminate\Http\JsonResponse
*/
public function register(Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|string|between:2,100',
'email' => 'required|string|email|max:100|unique:users',
'password' => 'required|string|confirmed|min:6',
]);
if($validator->fails()){
return response()->json($validator->errors(), 422);
}
$user = User::create(array_merge(
$validator->validated(),
['password' => bcrypt($request->password)]
));
return response()->json([
'message' => 'User successfully registered',
'user' => $user
], 201);
}
/**
* Log the user out (Invalidate the token).
*
* #return \Illuminate\Http\JsonResponse
*/
public function logout() {
auth()->logout();
return response()->json(['message' => 'User successfully signed out']);
}
/**
* Refresh a token.
*
* #return \Illuminate\Http\JsonResponse
*/
public function refresh() {
return $this->createNewToken(auth()->refresh());
}
/**
* Get the authenticated User.
*
* #return \Illuminate\Http\JsonResponse
*/
public function userProfile() {
return response()->json(auth()->user());
}
/**
* Get the token array structure.
*
* #param string $token
*
* #return \Illuminate\Http\JsonResponse
*/
protected function createNewToken($token){
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth()->factory()->getTTL() * 60,
'user' => auth()->user()
]);
}
}
User Model:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject, MustVerifyEmail
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
'email_verified_at'
];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier() {
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims() {
return [];
}
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
Please give some solution, Thanks
Option1
So one way i handle this is by checking the email_verified_at column on your user.
when a user logs in check if email_verified_at exists.
I also have a separate table called user_verification_tokens which contain a userID, token, and tokenExpiryDate
if it doesn't exist you can enforce verification by not logging them in until they verify their email. This could send a email to the user.
When the email gets generated a UUID gets inserted into the token column in the user_verification_tokens and sent through to the email. When the user clicks on the email and it checks on an unauthenticated route if that token exists then updates the email_verified_at column.
Option2
Generate a OTP that that gets sent to the email
User manually enters OTP
Verify UserID + OTP exists
Update email_verified_at
i have an idea to use auth middleware to retrieve a user's products but currently i am not able to retrieve that user's products. Instead, it listed all the products of other users. Can you guys give me some ideas to help me complete it. Thank you !!!
This is my ProjectController code:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Resources\ProjectResource;
use App\Models\Project;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class ProjectController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$projects = Project::all();
return response([
'projects' => ProjectResource::collection($projects),
'message' => 'Retrieved successfully'
], 200);
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$data = $request->all();
$validator = Validator::make($data, [
// 'uuid' => 'required|unique:projects',
'user_id' => 'required',
'name' => 'required|max:255',
'status' => 'required',
]);
if ($validator->fails()) {
return response(['error' => $validator->errors(), 'Validation Error']);
}
$projects = Project::create($data);
return response(['projects' => new ProjectResource($projects), 'message' => 'Created successfully'], 201);
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show(Project $project)
{
return response(['project' => new ProjectResource($project), 'message' => 'Retrieved successfully'], 200);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, Project $project)
{
$project->update($request->all());
return response(['project' => new ProjectResource($project), 'message' => 'Update successfully'], 200);
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy(Project $project)
{
$project->delete();
return response(['message' => 'Deleted'], 204);
}
}
This is my ProjectModel code:
<?php
namespace App\Models;
use App\Enums\ProjectStatus;
use App\Http\Traits\Uuid;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class Project extends Model
{
use HasFactory;
use Uuid;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'status',
'user_id',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'id',
'uuid',
];
protected $cast = [
'status' => ProjectStatus::class
];
public function setUuidAttribute()
{
$this->attributes['uuid'] = Str::uuid();
}
}
This is my API Router code:
You have to retrieve the user first in order to filter the products. There are multiple ways to do that. Here's a link to Laravel's documentation on the subject: https://laravel.com/docs/8.x/authentication#retrieving-the-authenticated-user
You also have to filter your query (your query being Project::all()) so that it only retrieves the products for the user. Here's a link to some Laravel documentation related to that: https://laravel.com/docs/8.x/eloquent#retrieving-models
In the end, replacing this $projects = Project::all(); with this $projects = Project::where('user_id', auth()->user()->id); should do the trick.
Try this
public function index()
{
$projects = Project::where('user_id', auth()->id())->get();
return response([
'projects' => ProjectResource::collection($projects),
'message' => 'Retrieved successfully'
], 200);
}
I'm trying to send the form information to database but when i submit the form this error appears:
ErrorException
Declaration of App\Http\Controllers\LivroController::authorize() should be compatible with App\Http\Controllers\Controller::authorize($ability, $arguments = Array)
CONTROLLER (LivroController)
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreUpdateLivro;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Livro;
class LivroController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
protected $request;
private $repository;
private $livro;
public function __construct(Livro $livro)
{
$this->livro = $livro;
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/* public function index()*/
// {
/* $title = 'listagem dos livros';
$livros = $this->livro->all();
return view ('livros/cadastro', compact('livros','title'));*/
// return view ('livros/cadastro');
// }
protected function validator(Request $request)
{
return Validator::make($request, [
'namel' => ['required', 'string', 'max:200'],
'autor' => ['required', 'string', 'email', 'max:200'],
'editora' => ['required', 'string', 'max:50'],
'categoria'=> ['required', 'string', 'min:50'],
'classificação'=> ['required', 'string', 'min:1','max:2'],
'descricao'=> ['required', 'string', 'min:200'],
'image'=> ['not required'],
]);
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function create(StoreUpdateLivro $request)
{
$user = Auth::user()->id;
$data = $request->all();
if($request->image->isValid()){
$image = $request->image->store('livros');
$data['image'] = $image;
}
Livro::create([
'users_id' => $user,
'namel' => $request['namel'],
'autor' => $request['autor'],
'editora' => $request['editora'],
'categoria'=> $request['categoria'],
'classificação'=>$request['classificação'] ,
'descricao'=>$request['descricao'],
'image'=>$request['image'],
]);
return view('livros/cadastro');
}
public function index()
{
$livro = DB::select('select * from livros');
return view('livros/mostrar_livros', [
'livro' => $livro,
]);
}
}
Remove authorize() method from LivroController and then,
go to StoreUpdateLivro file and set return true into authorize() method.
and also you don't need to validator method in your controller.
See more about the FormRequest in Laravel.
I think, you have a copy/paste problem
Delete LivroController:: authorize() method - you copied it from Form Request - and all will be work fine.
I have a question about showing posts from specific user. I'm building a basic keeping records website for my brothers company. I made a redirected login for normal users(workers in company) and for admin(company manager). So I'm new at Laravel and programming, a did everything for this website and all I need is how to show posts on admin profile for specific user. On admin profile I'll make pages for all workers profiles and on specific page I need to show posts for that specific user. How can I do that? Making new Controller?
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Post;
class PostsController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$post = Post::all();
return view('posts.tabela')->with('posts', $post);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('posts.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request, [
'br_kesice' => 'required',
'ime' => 'required',
'br_telefona' => 'required',
'posao' => 'required',
'cijena' => 'required',
'placanje' => 'required',
'popust' => 'required',
'datum_preuz' => 'required',
'datum_izdav' => 'required',
'smjena' => 'required',
'radnik' => 'required',
'status' => 'required'
]);
$post = new Post;
$post->br_kesice = $request->input('br_kesice');
$post->ime = $request->input('ime');
$post->br_telefona = $request->input('br_telefona');
$post->posao = $request->input('posao');
$post->cijena = $request->input('cijena');
$post->placanje = $request->input('placanje');
$post->popust = $request->input('popust');
$post->datum_preuz = $request->input('datum_preuz');
$post->datum_izdav = $request->input('datum_izdav');
$post->smjena = $request->input('smjena');
$post->radnik = $request->input('radnik');
$post->status = $request->input('status');
$post->user_id = auth()->user()->id;
$post->save();
return redirect('/home');
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
$post = Post::find($id);
if(auth()->user()->id !==$post->user_id){
return redirect('/posts')->with('error', 'Nedozvoljen pristup!');
}
return view('posts.edit', compact('post', 'id'))->with('post', $post);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->validate($request, [
'br_kesice' => 'required',
'ime' => 'required',
'br_telefona' => 'required',
'posao' => 'required',
'cijena' => 'required',
'placanje' => 'required',
'popust' => 'required',
'datum_preuz' => 'required',
'smjena' => 'required',
'radnik' => 'required',
'status' => 'required'
]);
$post = Post::find($id);
$post->br_kesice = $request->input('br_kesice');
$post->ime = $request->input('ime');
$post->br_telefona = $request->input('br_telefona');
$post->posao = $request->input('posao');
$post->cijena = $request->input('cijena');
$post->placanje = $request->input('placanje');
$post->popust = $request->input('popust');
$post->datum_preuz = $request->input('datum_preuz');
$post->datum_izdav = $request->input('datum_izdav');
$post->smjena = $request->input('smjena');
$post->radnik = $request->input('radnik');
$post->status = $request->input('status');
$post->save();
return redirect('/home');
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\User;
class Post extends Model
{
protected $table = 'posts';
public $primaryKey = 'id';
public $timestamps = true;
public function user(){
return $this->belongsTo('App\User');
}
}
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Post;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function posts(){
return $this->hasMany('App\Post');
}
public function is_admin(){
if($this->admin)
{
return true;
}
return false;
}
}
I want to extend/overwrite my LinkedInProvider.php (in vendor\laravel\socialite\src\Two) to add new fields in the Linkedin Request.
I've create a new LinkedInProvider.php (in app\Providers) with the following code :
namespace App\Providers;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;
class LinkedInProvider extends AbstractProvider implements ProviderInterface
{
/**
* The scopes being requested.
*
* #var array
*/
protected $scopes = ['r_basicprofile', 'r_emailaddress'];
/**
* The separating character for the requested scopes.
*
* #var string
*/
protected $scopeSeparator = ' ';
/**
* The fields that are included in the profile.
*
* #var array
*/
protected $fields = [
'id', 'first-name', 'last-name', 'formatted-name',
'email-address', 'headline', 'location', 'industry', 'positions',
'public-profile-url', 'picture-url', 'picture-urls::(original)',
];
/**
* {#inheritdoc}
*/
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://www.linkedin.com/oauth/v2/authorization', $state);
}
/**
* {#inheritdoc}
*/
protected function getTokenUrl()
{
return 'https://www.linkedin.com/oauth/v2/accessToken';
}
/**
* Get the POST fields for the token request.
*
* #param string $code
* #return array
*/
protected function getTokenFields($code)
{
return parent::getTokenFields($code) + ['grant_type' => 'authorization_code'];
}
/**
* {#inheritdoc}
*/
protected function getUserByToken($token)
{
$fields = implode(',', $this->fields);
$url = 'https://api.linkedin.com/v1/people/~:('.$fields.')';
$response = $this->getHttpClient()->get($url, [
'headers' => [
'x-li-format' => 'json',
'Authorization' => 'Bearer '.$token,
],
]);
return json_decode($response->getBody(), true);
}
/**
* {#inheritdoc}
*/
protected function mapUserToObject(array $user)
{
return (new User)->setRaw($user)->map([
'id' => $user['id'], 'nickname' => null, 'name' => Arr::get($user, 'formattedName'),
'email' => Arr::get($user, 'emailAddress'), 'avatar' => Arr::get($user, 'pictureUrl'),
'avatar_original' => Arr::get($user, 'pictureUrls.values.0'),
]);
}
/**
* Set the user fields to request from LinkedIn.
*
* #param array $fields
* #return $this
*/
public function fields(array $fields)
{
$this->fields = $fields;
return $this;
}
}
But now, I've got this error :
Type error: Argument 1 passed to Laravel\Socialite\Two\AbstractProvider::__construct() must be an instance of Illuminate\Http\Request, instance of Illuminate\Foundation\Application given, called in G:\laragon\www\localhost\vendor\laravel\framework\src\Illuminate\Foundation\ProviderRepository.php on line 201
I know I can install Socialite Manager, but I just want to overwrite the fields list to add new field (like position and industry)
You shouldn't have to overwrite/extend the whole class. In the Laravel\Socialite\Two\User object that is being created, there is a $user property, which contains the raw information the provider sent back.
When making the request, you can set the fields you want LinkedIn to return in your controller method:
public function redirectToProvider()
{
$fields = [
'id', 'first-name', 'last-name', 'formatted-name',
'email-address', 'headline', 'location', 'industry',
'public-profile-url', 'picture-url', 'picture-urls:(original)',
'positions', 'summary' // <-- additional fields here
];
return Socialite::driver('linkedin')->fields($fields)->redirect();
}
You can see two additional fields being requested, positions and summary, which aren't included by default.
Happy hacking!