I'm working on simple laravel9 project on my localhost where you can login via Facebook or Twitter.
I added custom domain to my localhost with verified ssl.
composer require laravel/socialite
already installed.
Facebook login works fine but twitter shows Erorr:
League\OAuth1\Client\Credentials\CredentialsException Received HTTP status code [401] with message "{"errors":[{"code":32,"message":"Could not authenticate you."}]}" when getting temporary credentials.
Here is my TwitterController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Laravel\Socialite\Facades\Socialite;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use Exception;
class TwitterController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function redirectToTwitter()
{
return Socialite::driver('twitter')->redirect();
}
/**
* Create a new controller instance.
*
* #return void
*/
public function handleTwitterCallback()
{
try {
$user = Socialite::driver('twitter')->user();
$finduser = User::where('twitter_id', $user->id)->first();
if($finduser){
Auth::login($finduser);
return redirect()->intended('/home');
}else{
$newUser = User::updateOrCreate(['email' => $user->email],[
'name' => $user->name,
'twitter_id'=> $user->id,
'username'=> $user->id,
'uid' => rand(9,999999999)+time(),
'password' => encrypt('123456dummy')
]);
Auth::login($newUser);
return redirect()->intended('/home');
}
} catch (Exception $e) {
dd($e->getMessage());
}
}
}
config/services.php
'twitter' => [
'client_id' => env('TWITTER_CLIENT_ID'),
'client_secret' => env('TWITTER_CLIENT_SECRET'),
'redirect' => 'https://testsite.com/auth/twitter/callback',
],
login.blade.php
{{-- Login with Twitter --}}
<div class="mt-4 p-3 d-flex justify-content-center">
<a class="btn mr-1" href="{{ route('auth.twitter') }}"
style="background: #1D9BF9; color: #ffffff; padding: 10px; width: 30%; text-align: center; border-radius:3px;">
Twitter
</a>
</div>
routes/web.php
Route::controller(TwitterController::class)->group(function(){
Route::get('auth/twitter', 'redirectToTwitter')->name('auth.twitter');
Route::get('auth/twitter/callback', 'handleTwitterCallback');
});
.env
TWITTER_CLIENT_ID=xxxxxxxxxxxxxxxx
TWITTER_CLIENT_SECRET=xxxxxxxxxxxxxxx
composer.json
"require": {
"php": "^7.3|^8.0",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^8.75",
"laravel/sanctum": "^2.11",
"laravel/socialite": "^5.5",
"laravel/tinker": "^2.5",
"laravel/ui": "^3.4",
"socialiteproviders/twitter": "^4.1"
},
I know that my thread is duplicated but I searched alot and found that there are many people didn't find a clean solution yet.
I also tried this:
composer require socialiteproviders/twitter
as provided by laravel docs for other login providers using this https://socialiteproviders.com/Twitter/#installation-basic-usage
tried also to add providers to config/app which are not needed as I know
'providers' => [ Laravel\Socialite\SocialiteServiceProvider::class,],
'aliases' => [ 'Socialite' => Laravel\Socialite\Facades\Socialite::class,],
here is my twitter application screenshot:
Environment:staging
Solved !
App keys where somehow broken so I regenerate them.
and the other issue was misspilling in call back URL on Twitter app
Related
I am starting with stripe and still in test mode.
I use Laravel 9 + cashier and vuejs
I also installed vue-stripe and created a view to test the checkout functionality.
Here is my vue
<template>
<div class="text-xl sass-editor-1 text-center">
<h1 class="text-2xl">Stripe Payment Gateway integration</h1>
<div class="container" v-if="payId">
<stripe-checkout
ref="checkoutRef"
:pk="publishableKey"
:sessionId="payId"
:customerEmail="customerEmail" />
<button class="border-2 rounded-lg bg-green-800 text-white p-3 mt-4" #click="submit">Pay Now!</button>
</div>
{{customerEmail}}
<div v-if="subscribeId" class="container">
<stripe-checkout
ref="subRef"
:pk="publishableKey"
:sessionId="subscribeId"
:customerEmail="customerEmail" />
<button class="border-2 rounded-lg bg-green-800 text-white p-3 mt-4" #click="submitSub">Subscribe Now!</button>
</div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue';
import { StripeCheckout , Stripe} from '#vue-stripe/vue-stripe';
import axios from "../axios"
import store from "../store"
export default {
components: {
StripeCheckout,
},
data() {
return {
publishableKey: 'pk_test_51M6ZtzI....................XgAyUVjlwG6MFos0AaqaQYJOf2YC3a6oWlZqMjFtTZj00Tue51qVs',
payId: null,
subscribeId: null,
customerEmail: store.state.user.email
}
},
methods: {
getSession() {
axios.get('api/getSession')
.then(res => {
console.log(res);
this.payId = res.data.oneTime.id;
this.subscribeId = res.data.sub.id;
})
.catch(err => {
console.log(err);
})
},
submit() {
this.$refs.checkoutRef.redirectToCheckout();
},
submitSub() {
this.$refs.subRef.redirectToCheckout();
}
},
mounted() {
this.getSession();
}
}
</script>
and here is the StripeController to return the sessionId in the backend
<?php
namespace App\Http\Controllers;
use Stripe\StripeClient;
use Illuminate\Http\Request;
use Laravel\Cashier\Cashier;
class StripeController extends Controller
{
public function getSession()
{
$stripe = new StripeClient(env('STRIPE_SECRET'));
$user=auth()->user();
$stripeCustomer = $user->createOrGetStripeCustomer(
['name'=>$user->name,'email'=>$user->email]);
$checkout = $stripe->checkout->sessions->create(
[
'success_url' => 'https://yahoo.com',
'cancel_url' => 'https://google.com',
'line_items' =>
[
[
'price_data' =>
[
'currency' => 'eur',
'unit_amount' => 500,
'product_data' =>
[
'name' => 'Example Stripe Checkout'
],
],
'quantity' => 1,
],
],
'mode' => 'payment',
]
);
$sub = $stripe->checkout->sessions->create(
[
'success_url' => 'https://denentzat.fr',
'cancel_url' => 'https://google.com',
'line_items' =>
[
[
'price'=>'price_1M84UNIWDjpHNQK1FXOj1k01',
'quantity' => 1,
],
],
'mode' => 'subscription',
]
);
return ['oneTime'=>$checkout, 'sub'=>$sub];
}
public function webhook(Request $request){
\Log::info($request->data);
return response()->json(['status'=>'success']);
}
}
The payment is done in both cases (pay or subscribe).
Nevertheless, when I go in the customer tab of the dashboard, I can see that sometimes (I could not find for what reason) stripe create a guest user, or a normal user and
eventually, there may be several users with the same email. How to prevent this?
I was hoping that in passing the user email to the form (Stripe-checkout component) this will prefill the email field but it doesn't happen.
Thank you for help.
You can pre-create a Customer with their email, then passing in the Customer Id when creating the Checkout Session. (see Existing Customer on Stripe Doc).
I have implemented an authentication system with NUXT framework and using laravel 9 Sanctum as the backend.
While logging in it works fine it update the store and everything is fine but while registering a user it gives a "Request failed with status code 419" "message": "CSRF token mismatch." errors:
this is my api.php file in laravel
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AuthController;
use App\Http\Controllers\TopicController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
//public routes
Route::post('register', [AuthController::class, 'reg']);
Route::post('login', [AuthController::class, 'login']);
Route::post('logout', [AuthController::class, 'logout']);
//protected routes by sanctum
Route::group(['middleware' => ['auth:sanctum']], function() {
Route::get('/user', function (Request $request) {
return $request->user();
});
});
This is my AuthController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Requests\UserRegisterRequest;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
use Illuminate\Http\Respose;
use Illuminate\Auth\AuthenticationException;
use App\Http\Resources\User as UserResource;
class AuthController extends Controller
{
//register a user
public function reg(Request $request) {
$user_data = $request->validate([
'name' => 'required|string',
'email' => 'required|string|unique:users,email',
'password' => 'required|string|confirmed'
]);
$user = User::create([
'name' => $user_data['name'],
'email' => $user_data['email'],
'password' => bcrypt($user_data['password'])
]);
}
public function login(Request $request){
if($user = !auth()->attempt($request->only('email','password'))){
throw new AuthenticationException();
}
$token = auth()->user()->createToken('myapptoke')->plainTextToken;
return (new UserResource($request->user()))->additional([
'meta' => [
'token' => $token,
],
]);
}
//logout a user
public function logout(Request $request){
auth()->user()->tokens()->delete();
auth()->logout();
$response = [
'message' => 'logged out'
];
return $response;
}
}
Laravel .env file
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:D2F/NZpkDyj1hyCCzTKe3i/5khtp/WX1k17udQjv9R8=
APP_DEBUG=true
APP_URL=
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=backend-laravel-nine
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
SANCTUM_STATEFUL_DOMAINS=localhost:3000
SESSION_DOMAIN=localhost
This is my nuxt.config.js
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'NUXTfreshInstallation',
htmlAttrs: {
lang: 'en',
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' },
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{rel:'stylesheet', href:'/css/bootstrap.min.css'}
],
scripts: [
{type:'text/javascript', serc:'/js/bootstrap.min.js'},
{type:'text/javascript', serc:'/js/bootstrap.bundle.min.js'},
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [ "./plugins/mixins/user.js", "./plugins/mixins/validation.js","./plugins/setErrorsPlugin.js"],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
'#nuxtjs/auth-next',
],
// router: {
// middleware: ["clearValidationErrors"]
// },
auth: {
strategies: {
laravelSanctum: {
provider: 'laravel/sanctum',
url: 'http://localhost:8000',
endpoints: {
login: {
url: '/api/login',
method: 'post',
//propertyName: 'meta.token'
},
user: {
url: '/api/user',
//method: 'get',
//propertyName: 'data'
},
logout: {
url: '/api/logout',
//method: 'post',
},
},
}
},
redirect: {
login: '/login',
logout: '/login',
home: '/'
}
},
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
// Workaround to avoid enforcing hard-coded localhost:3000: https://github.com/nuxt-community/axios-module/issues/308
baseURL: 'http://localhost:8000',
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {},
}
This is the user register .vue page:
<template>
<div>
<div class="container col-md-6 mt-5">
<h2>Register</h2>
<hr>
<form #submit.prevent="register" method="post">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" placeholder="Enter Name" v-model="form.name" autofocus/>
<small class="form-text text-danger">Show errors</small>
</div>
<div class="form-group">
<label>Email address</label>
<input type="email" class="form-control" placeholder="Enter Email" v-model.trim="form.email" />
<small class="form-text text-danger">Show errors</small>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" v-model.trim="form.password" placeholder="Enter Password" />
<small class="form-text text-danger">Show errors</small>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" class="form-control" v-model.trim="form.password_confirmation" placeholder="Enter Password Again" />
<small class="form-text text-danger">Show errors</small>
</div>
<button type="submit" class="btn btn-primary" >Register</button>
<p> Already have an account <nuxt-link to="/Login">Login </nuxt-link></p>
</form>
</div>
</div>
</template>
<script>
export default {
data () {
return {
form: {
name: '',
email: '',
password: '',
password_confirmation: '',
},
}
},
methods: {
async register (){
await this.$axios.post('/api/register', this.form);
await this.$auth.loginWith('laravelSanctum', {
data: {
email: this.form.email,
password: this.form.password
}
});
}
}
}
</script>
I have tried may troubleshooting techniques, I understood a little that the problem is in my .env file in "SANCTUM_STATEFUL_DOMAINS=localhost:3000 SESSION_DOMAIN=localhost "
if i add write it like this SANCTUM_STATEFUL_DOMAINS=localhost:3000,.localhost then the login does not work.
Is there any solutions I will appreciate your help Thanks
This is the error i get from the register request
Try to add csrf token into your registration view like this:
<form #submit.prevent="register" method="post">
#csrf
<div class="form-group">
<label>Name</label>
...
Try to change
SANCTUM_STATEFUL_DOMAINS=localhost:3000
to
SANCTUM_STATEFUL_DOMAINS=http://localhost:3000
I have been looking online but i can't find any way of doing it. Let me explain, i have an API (Laravel passport on lumen), i tested it with Postman, i get my access token with oauth, everything is fine. Now i have another Laravel application and i want to know how i can keep all my authentification stuff using the API to login. I have seen lot of apps that actualy retrieve an api_token and they use 'Auth::user()->where('api_token', $token)'. But i find this wrong because i don't want my client to have access to the database, i want every request to the database to be handled by the API. Is that possible?
Let say you want to login to a laravel backend app via api. make sure you install guzzle.
Route(api): Route::POST('/login', 'AuthController#login')
Controller: AuthController.php
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|string',
]);
$http = new \GuzzleHttp\Client;
try {
$response = $http->post(config('services.passport.login_endpoint'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => 'your client_id',
'client_secret' => 'your client_secret',
'username' => $request->email,
'password' => $request->password,
// 'scope' => '',
],
]);
return $response->getBody();
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
if ($e->getCode() == 401) {
return response()->json(['message' => 'This action can\'t be perfomed at this time. Please try later.'], $e->getCode());
} else if ($e->getCode() == 400) {
return response()->json(['message' => 'These credentials do not match our records.'], $e->getCode());
}
return response()->json('Something went wrong on the server. Please try letar.', $e->getCode());
}
}
In your front-end app for example vuejs, even laravel using vue component. As you can see, i'm using boostrap-vue but feel free to use the regular html elements
<template>
<div>
<form #submit.prevent="login()">
<b-form-group label="Email">
<b-input placeholder="E-Mail" class="ml-1" v-model="form.email" type="email" name="email" :class="{ 'is-invalid': form.errors.has('email') }"/>
<has-error :form="form" field="email"></has-error>
</b-form-group>
<b-form-group>
<div slot="label" class="d-flex justify-content-between align-items-end">
<div>Password</div>
Forgot password?
</div>
<b-input v-model="form.password" type="password" name="password" :class="{ 'is-invalid': form.errors.has('password') }" />
<has-error :form="form" field="password"></has-error>
</b-form-group>
<div class="d-flex justify-content-between align-items-center m-0">
<b-check v-model="form.rememberMe" class="m-0">Remember me</b-check>
<b-btn type="submit" variant="primary">Sign In</b-btn>
</div>
</form>
</div>
<template>
<script>
export default ({
name: 'pages-authentication-login-v2',
metaInfo: {
title: 'Login'
},
state: {
token: localStorage.getItem('access_token'),
},
mutations: {
login(state, token) {
state.token = token
},
},
data: () => ({
form: new Form({
email: '',
password: '',
})
}),
methods: {
login(){
this.form.post('/api/login')
.then((response) =>{
const token = response.data.access_token
localStorage.setItem('access_token', token)
// console.log(response);
this.$router.push('/dashboard');
})
.catch((error)=>{
this.$toasted.error('Ooops! Something went wrong', {
icon : "warning",
theme: "bubble",
closeOnSwipe: true,
position: "top-right",
duration : 5000,
singleton: true,
})
});
},
}
})
</script>
I've used redirect back with input many times previously. But in this project I'm unable to do so. This is my controller method that handles the form request:
public function verifyMobileCode( Request $request)
{
$userId = Auth::user()->id;
if( Auth::user()->verification_code == $request['verification_code'])
{
User::where('id', $userId)->update(['verified'=>1]);
return redirect('/')->with('success', 'Account verified.');
}
else
{
return redirect()->back()->withErrors('verification_code' ,'unv' )->withInput($request->all());
}
}
This is my form blade:
#extends('layouts.index')
#section('content')
<div class="container" style='padding-top: 150px;'>
<?php var_dump($errors) ; ?>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Verify your mobile</div>
<div class="panel-body">
<form class="form-horizontal" method="POST" action="{{ route('verifyMobileCode') }}">
{{ csrf_field() }}
<div class="form-group{{ $errors->has('verification_code') ? ' has-error' : '' }}">
<label for="verification_code" class="col-md-4 control-label">Verification code</label>
<div class="col-md-6">
<input id="verification_code" type="text" class="form-control" name="verification_code" value="{!! old('verification_code') !!}" required autofocus maxlength="6" pattern="\d{6}">
#if ($errors->has('verification_code'))
<span class="help-block">
<strong>Please enter 6 digit number sent to your mobile.</strong>
</span>
#endif
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Register
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
#endsection
My Kernel.php is as follows:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\LanguageSwitcher::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'is-admin' => \App\Http\Middleware\IsAdminMiddleware::class,
];
}
I do not find any error or something wrong. Is there anything you see? Is there any technique to debug this behaviour? Thaks in advance.
My approach would be using FormRequest.
php artisan make:request VerifyCodeRequest
And body of the request:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class VerifyCodeRequest 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 [
'verification_code' => 'required|in:'.$this->user()->verification_code, // since user is already logged in we check if verification_code matches using `in` rule
];
}
public function messages()
{
return [
'in' => 'Your custom error message if we failed',
];
}
}
Now you change signature of verifyMobileCode(...) to the following verifyMobileCode(App\Http\Requests\VerifyCodeRequest $request).
Now, code executes body of the function only if we pass the validation so we need to update user instance and we are done.
public function verifyMobileCode(App\Http\Requests\VerifyCodeRequest $request)
{
$request->user()->verify();
return redirect('/')->with('success', 'Account verified.');
}
Inside User model add verify() function
public function verify()
{
$this->update(['verified' => true]);
}
If your above approach does not work the there is some issue with your app/Http/Kernel.php. You have used
\Illuminate\Session\Middleware\StartSession::class,
twice. You must delete one. Probably the first one.
See the stock Laravel's kernel.php.
Replace ->withInput($request->all()); with ->withInput();
if you dont want any one of the input use
->withInput(
$request->except('input_name')
);
To debug this without resorting to Xdebug the quick way is to add temporary debug code to the start of the blade file:
#php
dd($errors->toArray(), $errors->has('verification_code'));
#endphp
Which will give you the following output:
array:1 [
0 => array:1 [
0 => "verification_code"
]
]
false
This shows that the logic in the blade file is not being evaluated to true which is required to show the error styles and message.
The quick fix is to change the controller to use:
->withErrors(['verification_code' => 'unv'])
withErrors expects as MessageBag or array, but will cast a string to an array which does not result in the proper key/value pair.
The debug output will now show:
array:1 [
"verification_code" => array:1 [
0 => "unv"
]
]
true
The debug code can now be removed and the error should be displayed as you expect.
The proper Laravel way is probably to use $request->validate() or a FormRequest for complex forms. For more information see the Laravel validation documentation (https://laravel.com/docs/5.5/validation).
Your Controller should look like this:
public function verifyMobileCode( Request $request)
{
$userId = Auth::user()->id;
if( Auth::user()->verification_code == $request['verification_code'])
{
User::where('id', $userId)->update(['verified'=>1]);
return redirect('/')->with('success', 'Account verified.');
}
else
{
return redirect()->back()->withErrors('message' ,'Please some errors encountered.' );
}
}
And modify this
<div class="form-group{{ $errors->has('verification_code') ? ' has-error' : '' }}">
To this:
<div class="form-group>
#include('errors');
Also create file called errors.blade.php in resources/views and put the following code:
#if ($errors->any())
<div class="card"> //incase bootstrap 4
<div class="error card-body alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
</div>
#endif
Hope it works for you. But you dont need to display old inputs since the code will be wrong or something wrong has happened. So its not necessary
return redirect()->back()->withInput()->withErrors('verification_code' ,'unv' );
In controller
return redirect()->back()->withErrors('verification_code' ,'unv')->withInput();
In view
if you want to retrieve the validated input field value then you need to use laravel FORM class for <form></form> as well as <input> fields
example
{{ Form::open(['method' => 'post','url' => 'Your url','class'=>'form-horizontal']) }}
{{ Form::text('verification_code','',['class'=>'form-control']) }}
{{ Form::close() }}
anybody on Laravel 8, this should work
return back()->withErrors('your error message is here');
If you look at the signature of the withErrors function, second param is the key and it is set to default unless you want it to be something specific.
I've ran into a strange issue regarding validations in Laravel 5.2. I reviewed following questions on StackOverflow, but none of them seems to apply to my case:
Laravel validation not showing errors
Laravel Validation not returning error
The thing is, that I am trying to validate a title field, before persisting the Card object into the database. When I submit the form with an empty title field, as expected, It doesn't pass the validations. However, the $errors array doesn't get populated upon failure of the mentioned validations. Can anybody explain where am I going wrong with this code?
/////////////////////// CONTROLLER /////////////////////
public function create(Request $request)
{
$this->validate($request, [
'title' => 'required|min:10'
]);
Card::create($request->all());
return back();
}
///////////////////////// VIEW /////////////////////////
// Show errors, if any. (never gets triggered)
#if(count($errors))
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif
<form method="POST" action="/cards">
{{ csrf_field() }}
<div class="form-group">
// The textarea does not get populated with the 'old' value as well
<textarea class="form-control" name="title">{{ old('title') }}</textarea>
</div>
<div class="form-group">
<button class="btn btn-primary" type="submit">Add Card</button>
</div>
</form>
If you are running Laravel 5.2.27 and up, you no longer need to use the web middleware group. In fact, you shouldn't add it to your routes because it's now automatically applied by default.
If you open up your app/Http/RouteServiceProvider.php file, you will see this bit of code:
protected function mapWebRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace, 'middleware' => 'web',
], function ($router) {
require app_path('Http/routes.php');
});
}
Source: https://github.com/laravel/laravel/blob/master/app/Providers/RouteServiceProvider.php#L53
As you can see, it's automatically applying the web middleware for you. If you try to apply it again (more than once) in your routes file, you'll run into weird problems like what you are currently facing.
In order to find out the version of Laravel that you are running, run this command: php artisan --version
I guess you have to set the if clause to #if(count($errors) > 0)
In your controller, try adding a $validator->fails() statement, and using ->withErrors() to return any errors to your template.
public function create(Request $request)
{
$validator = Validator::make($request->all(), [
'title' => 'required|min:10'
]);
if ($validator->fails()) {
return back()->withErrors($validator);
}
Card::create($request->all());
return back();
}