Laravel 5.4 change default username and password fields - laravel

I inherited an application that I am currently porting to laravel. They already have the database designed and they use different tables for authentication than the defaults for laravel. In the database, they have upper case field names.
The emails are saved in a field called MCP_EMAIL and the password are saved in a field called MCP_PASSWORD
I have managed to change the registration process and users can register fine.
The problem is with login. When you attempt to login, nothing happens. No error messages, no logs, nothing. It just keeps coming back to the login page!
Here is the user class.
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $table = "user_profiles";
protected $primaryKey ="MCP_ID";
protected $rememberTokenName = 'MCP_REMEMBER_TOKEN';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'MCP_DISPLAY_NAME', 'MCP_EMAIL', 'MCP_PASSWORD',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
const CREATED_AT = "ADDED";
const UPDATED_AT = "MODIFIED";
public function getAuthPassword(){
return $this->MCP_PASSWORD;
}
//seems to be a repetition of protected$rememberTokenName
public function getRememberTokenName()
{
return $this->MCP_REMEMBER_TOKEN;
}
}
And the login controller
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facade\Auth;
use Log;
class LoginController extends Controller
{
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function username(){
return 'MCP_EMAIL';
}
}
What am I missing? Why can't I see any error messages?
Update
I was doing everything right. Besides doing everything above, you need to change the name of the input in login.blade.php
<div class="form-group{{ $errors->has('MCP_EMAIL') ? ' has-error' : '' }}">
<label for="email" class="col-md-4 control-label">E-Mail Address</label>
<div class="col-md-6">
<input id="MCP_EMAIL" type="email" class="form-control" name="MCP_EMAIL" value="{{ old('MCP_EMAIL') }}" required autofocus>
#if ($errors->has('MCP_EMAIL'))
<span class="help-block">
<strong>{{ $errors->first('MCP_EMAIL') }}</strong>
</span>
#endif
</div>
</div>
See related question here

Did you know that L5.4 ships with pre-built authentication, to provide a quick way to scaffold you need to run php artisan auth:make, I'm pretty sure that you need to surcharge some functions within AuthenticatesUsers trait, unless the database columns. Check this out AuthenticatesUsers
In the case you don't use Authentication scaffolding :
1) there's no need to remove the AuthenticatesUsers from your LoginController
2) Try to implement your LoginController according this section Manually Authenticating Users

Related

eloquent relationship belongsTo('Spatie\Permission\Models\Role', 'id', 'id') not working

so i was following this tutorial [laravel 8 crud tutorial]1
and i wanted the create,edit,delete,show to be modal. i manage to make it work on show,delete and create but my edit is not working.
user.php (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 Spatie\Permission\Traits\HasRoles;
use Spatie\Permission\Models\Role;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable, HasRoles;
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function userRole()
{
return $this->belongsTo('Spatie\Permission\Models\Role', 'id', 'id');
}
}
Edit modal
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>{{ __('Role') }}:</strong>
{!! Form::select('roles[]', $roles,$user->userRole->name, array('class' => 'form-control','multiple')) !!}
</div>
</div>
if i remove the name in $user->userRole i get no error, but when i put a name in$user->userRole->name i get an error
Trying to get property 'name' of non-object (View: C:\Apache24\htdocs\BDProject_v1\resources\views\Users\modal\edit.blade.php)
Well, that means you are trying to get the property of a non-object. Please dump the value and check if it is an object or an array.
var_dump($user->userRole);

Laravel 8 latest login controller code | phone number login

I have several ways to log in with my phone number except for the default Laravel email. But failed. Here I added the full code of my login controller below.
In loginControlller.php: I added this
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller {
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
public function validateLogin(Request $request) {
dd($request->all());
}
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct() {
$this->middleware('guest')->except('logout');
}
public function username(){
return 'phone';
}
}
In login.blade.php: I added this
<div>
<x-label for="phone" :value="__('Phone')" />
<x-input id="phone" class="block mt-1 w-full" type="text" name="phone" :value="old('phone')" required autofocus />
</div>
Whenever I tried, this occurred

I am looking for a way to get an invald users not to logged on in the same way as not exist users

I am using Laravel 6 , looking for a way not to logged on in the same way as not existing users on the login screen.
I added a certain column to the users table that created by the default user-auth function.
the column type is "boolean". its name is "valid".
when a user who has a false "valid" column tries to log in, then I would like to get the login screen to say "the user does not exist."
login.blade.php
<div class="col-md-6">
<input id="email" type="email" class="form-control #error('email') is-invalid #enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
#error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</div>
When an Invalid user try to login , I would like to put "This account is invalid " to $message and display it.
You could just use the directives to check the state of user's valid. Something like this.
if (Auth::user()->valid) return redirect("yourAfterLoginRoute");
return redirect("yourFailAfterLoginRoute");
try this in your LoginController.
protected function credentials(Request $request)
{
$arr = $request->only($this->username(), 'password');
$arr['valid'] = true;
return $arr;
}
You could achieve this with Laravel Middleware.
Middleware provide a convenient mechanism for inspecting and filtering
HTTP requests entering your application. For example, Laravel includes
a middleware that verifies the user of your application is
authenticated. If the user is not authenticated, the middleware will
redirect the user to your application's login screen. However, if the
user is authenticated, the middleware will allow the request to
proceed further into the application.
Well, You could set up a middleware to be responsible for revoking/redirecting "invalid users".
Below are a few steps to point you in the suggested direction.
STEP 1
Generate the middleware: php artisan make:middleware RevokeInvalidUser
You will find the middleware in App\Http\Middleware directory.
STEP 2
Add your logic for revoking/redirecting "invalid users" in the new middleware's handle method.
// RevokeInvalidUser middleware.
<?php
namespace App\Http\Middleware;
use App\Models\User;
use Closure;
use Illuminate\Http\Request;
class RevokeInvalidUser
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if (
($request->method() === "POST")
&& ($request->path() === "login")
&& ($user = User::firstWhere("email", $request->email))
&& !$user->valid
) {
return redirect()
->back()
->with(["acInvalidMessage" => "This account is invalid."])
->withErrors([
"email" => "The user does not exist."
]);
}
return $next($request);
}
}
STEP 3
Register your middleware in the protected $middlewareGroups array of App\Http\Kernel.php class file.
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
// ...
protected $middlewareGroups = [
'web' => [
// ...
\App\Http\Middleware\RevokeInvalidUser::class,
],
// ...
}
STEP 4
Demo: For accessing the "This account is invalid" message in views, make this small tweak:
// Instead of:
<strong>{{ $message }}</strong> ❌
// Use this:
<strong>{{ session()->get('acInvalidMessage') ?? "" }}</strong> ✅
Addendum
NOTE: Anything below only applies if you don't have the "valid" column already.
In case you haven't created/added the column labelled "valid" on the users table, you can create it by running a migration. i.e:
Add the migration by running the command below in your terminal.
php artisan make:migration add_valid_column_on_users_table
Open the migration file found in your-project-root-directory/database/migrations. Edit it with the relevant lines of code.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddValidColumnOnUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table("users", function (Blueprint $table) {
$table->boolean("valid")->after("email")->default(true);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
}
}
Run your recently created migration against the database with the command below.
php artisan migrate
Test the implementation by invalidating some users. (changing a specific user's "valid" database column value to 0 on the users table.)

Manage settings in an application

Mine is a self-taught question, I would like to better understand how to best deal with the settings of an application in Laravel.
Assuming you have a table "Settings":
option
value
site_name
Example_name
site_description
Example_description
How can I handle the update issue? And how can I take them?
If you want to use out-of-the-box Laravel you can create a model to assist you with that. In order for you to create a model, you can run php artisan make:model Setting or you can create a model manually. Below is an example which you should place in a new file (Setting.php) in the /App/Models directory.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'Settings';
/**
* The primary key associated with the table.
*
* #var string
*/
protected $primaryKey = 'option';
/**
* Indicates if the model's ID is auto-incrementing.
*
* #var bool
*/
public $incrementing = false;
/**
* The data type of the auto-incrementing ID.
*
* #var string
*/
protected $keyType = 'string';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['option', 'value'];
}
You can then create a controller by running the following command: php artisan make:controller SettingController --resource --model=Setting. The command will automatically create a resource controller for the Setting model based on the Laravel documentation.
In your controller, you can request a certain value of one of your settings by using the following code:
// Retrieve a model by its primary key...
$site_name = Setting::find('site_name')->value;
Or you can request all settings listed in your database by using this line:
// Retrieve all settings
$settings = Setting::all();
You can further process the settings with code like this:
// Create a list of all options and associated values
foreach ($settings as $setting) {
echo $setting->option . ": " . $setting->value;
}
You can find way more information about Laravel models in the documentation and online.
I haven't tested the codes but they should work.
Update all options
If you want to update all options you should create a HTML form like this one:
<form action="{{ route('setting.update') }}" method="POST">
#csrf
#method('PUT')
#foreach ($settings as $setting)
<label>{{ $setting->option }}</label>
<input type="text" name="{{ $setting->option }}" value="{{ $setting->value }}"/>
#endforeach
<input type="submit">
</form>
In your update() function in your controller you can then update all values by using the following code:
public function update(Request $request)
{
$settings = Setting::update($request->all());
}
I'm not sure if the update will work correctly with the code above so please let me know :)
Spatie offer an open-source solution to managing laravel settings: https://github.com/spatie/laravel-settings I use a number of their other open-source solutions and they make life very easy.
Great material to learn from even if you decide not to use their package.

How to update specific fields in a PUT request?

I have a settings table where I store things like website title, social network links and other things... I make then all acessible by seting a cache variable.
Now, my question is, how can I update this table? By example... If I have the following blade form:
{!! Form::model(config('settings'), ['class' => 's-form', 'route' => ['setting.update']]) !!}
{{ method_field('PUT') }}
<div class="s-form-item text">
<div class="item-title required">Nome do site</div>
{!! Form::text('title', null, ['placeholder' => 'Nome do site']) !!}
</div>
<div class="s-form-item text">
<div class="item-title required">Descrição do site</div>
{!! Form::text('desc', null, ['placeholder' => 'Descrição do site']) !!}
</div>
<div class="s-form-item s-btn-group s-btns-right">
Voltar
<input class="s-btn" type="submit" value="Atualizar">
</div>
{!! Form::close() !!}
In the PUT request how can I search in the table by the each name passed and update the table? Here are the another files:
Route
Route::put('/', ['as' => 'setting.update', 'uses' => 'Admin\AdminConfiguracoesController#update']);
Controller
class AdminConfiguracoesController extends AdminBaseController
{
private $repository;
public function __construct(SettingRepository $repository){
$this->repository = $repository;
}
public function geral()
{
return view('admin.pages.admin.configuracoes.geral.index');
}
public function social()
{
return view('admin.pages.admin.configuracoes.social.index');
}
public function analytics()
{
return view('admin.pages.admin.configuracoes.analytics.index');
}
public function update($id, Factory $cache, Setting $setting)
{
// Update?
$cache->forget('settings');
return redirect('admin');
}
}
Repository
class SettingRepository
{
private $model;
public function __construct(Setting $model)
{
$this->model = $model;
}
public function findByName($name){
return $this->model->where('name', $name);
}
}
Model
class Setting extends Model
{
protected $table = 'settings';
public $timestamps = false;
protected $fillable = ['value'];
}
ServiceProvider
class SettingsServiceProvider extends ServiceProvider
{
public function boot(Factory $cache, Setting $settings)
{
$settings = $cache->remember('settings', 60, function() use ($settings)
{
return $settings->lists('value', 'name')->all();
});
config()->set('settings', $settings);
}
public function register()
{
//
}
}
Migration
class CreateSettingsTable extends Migration
{
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 100)->unique();
$table->text('value');
});
}
public function down()
{
Schema::drop('settings');
}
}
Ok, step by step.
First, let's think about what we really want to achieve and look at the implementation in the second step.
Looking at your code, I assume that you want to create an undefined set of views that contain a form for updating certain settings. For the user, the settings seem to be structured in groups, e.g. "General", "Social", "Analytics", but you don't structure your settings in the database like that. Your settings is basically a simple key/value-store without any relation to some settings group.
When updating, you want a single update method that handles all settings, disregarding which form the update request is sent from.
I hope I'm correct with my assumptions, correct me if I'm not.
Okay cool, but, come on, how do I implement that?
As always, there are probably a thousand ways you can implement something like this. I've written a sample application in order to explain how I would implement it, and I think it's pretty Laravelish (what a word!).
1. How should my data be stored?
We already talked about it. We want a basic key/value-store that persists in the database. And because we work with Laravel, let's create a model and a migration for that:
php artisan make:model Setting --migration
This will create a model and the appropriate migration. Let's edit the migration to create our key/value columns:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSettingsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('value');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('settings');
}
}
In the Setting model, we have to add the name column to the fillable array. I'll explain why we need to below. Basically, we want to use some nice Laravel APIs and therefore we have to make the name-attribute fillable.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model {
/**
* #var array
*/
protected $fillable = ['name'];
}
2. How do I want to access the settings data?
We discussed this in your last question, so I won't go into detail about this and I pretend that this code already exists. I'll use a repository in this example, so I will update the SettingsServiceProvider during development.
3. Creating the repositories
To make the dependencies more loosely coupled, I will create an Interface (Contract in the Laravel world) and bind it to a concrete implementation. I can then use the contract with dependency injection and Laravel will automatically resolve the concrete implementation with the Service Container. Maybe this is overkill for your app, but I love writing testable code, no matter how big my application will be.
app/Repositories/SettingRepositoryInterface.php:
<?php
namespace App\Repositories;
interface SettingRepositoryInterface {
/**
* Update a setting or a given set of settings.
*
* #param string|array $key
* #param string $value
*
* #return void
*/
public function update($key, $value);
/**
* List all available settings (name => value).
*
* #return array
*/
public function lists();
}
As you can see, we will use the repository for updating settings and listing our settings in a key/value-array.
The concrete implementation (for Eloquent in this example) looks like this:
app/Repositories/EloquentSettingRepository.php
<?php
namespace App\Repositories;
use App\Setting;
class EloquentSettingRepository implements SettingRepositoryInterface {
/**
* #var \App\Setting
*/
private $settings;
/**
* EloquentSettingRepository constructor.
*
* #param \App\Setting $settings
*/
public function __construct(Setting $settings)
{
$this->settings = $settings;
}
/**
* Update a setting or a given set of settings.
* If the first parameter is an array, the second parameter will be ignored
* and the method calls itself recursively over each array item.
*
* #param string|array $key
* #param string $value
*
* #return void
*/
public function update($key, $value = null)
{
if (is_array($key))
{
foreach ($key as $name => $value)
{
$this->update($name, $value);
}
return;
}
$setting = $this->settings->firstOrNew(['name' => $key]);
$setting->value = $value;
$setting->save();
}
/**
* List all available settings (name => value).
*
* #return array
*/
public function lists()
{
return $this->settings->lists('value', 'name')->all();
}
}
The DocBlocks should pretty much explain how the repository is implemented. In the update method, we make use of the firstOrNew method. Thats why we had to update the fillable-array in our model.
Now let's bind the interface to that implementation. In app/Providers/SettingsServiceProvider.php, add this to the register-method:
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(
\App\Repositories\SettingRepositoryInterface::class,
\App\Repositories\EloquentSettingRepository::class
);
}
We could have added this to the AppServiceProvider, but since we have a dedicated service provider for our settings we will use it for our binding.
Now that we have finished the repository, we can update the existing code in the boot-method of our SettingsServiceProvider so that it uses the repository instead of hardcoding App\Setting.
/**
* Bootstrap the application services.
*
* #param \Illuminate\Contracts\Cache\Factory $cache
* #param \App\Repositories\SettingRepositoryInterface $settings
*/
public function boot(Factory $cache, SettingRepositoryInterface $settings)
{
$settings = $cache->remember('settings', 60, function() use ($settings)
{
return $settings->lists();
});
config()->set('settings', $settings);
}
4. Routes and controller
In this simple example, the homepage will show a form to update some settings. Making a PUT/PATCH-request on the same route will trigger the update method:
<?php
get('/', ['as' => 'settings.index', 'uses' => 'Admin\SettingsController#index']);
put('/', ['as' => 'settings.update', 'uses' => 'Admin\SettingsController#update']);
The index-method of our controller will return a view that contains the form. I've commented the update method throughout to explain what each line does:
app/Http/Controllers/Admin/SettingsController.php:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Contracts\Cache\Factory;
use Illuminate\Http\Request;
use App\Repositories\SettingRepositoryInterface;
class SettingsController extends AdminBaseController {
/**
* #var \App\Repositories\SettingRepositoryInterface
*/
private $settings;
/**
* SettingsController constructor.
*
* #param \App\Repositories\SettingRepositoryInterface $settings
*/
public function __construct(SettingRepositoryInterface $settings)
{
$this->settings = $settings;
}
/**
* Shows the setting edit form.
*
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
return view('settings.index');
}
/**
* Update the settings passed in the request.
*
* #param \Illuminate\Http\Request $request
* #param \Illuminate\Contracts\Cache\Factory $cache
*
* #return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request, Factory $cache)
{
// This will get all settings as a key/value array from the request.
$settings = $request->except('_method', '_token');
// Call the update method on the repository.
$this->settings->update($settings);
// Clear the cache.
$cache->forget('settings');
// Redirect to some page.
return redirect()->route('settings.index')
->with('updated', true);
}
}
Note the first statement in the update method. It will fetch all POST-data from the request, except the method and CSRF token. $settings is now an associative array with your settings sent by the form.
5. And last, the views
Sorry for the Bootstrap classes, but i wanted to style my example app real quick :-)
I guess that the HTML is pretty self-explanatory:
resources/views/settings/index.blade.php:
#extends('layout')
#section('content')
<h1>Settings example</h1>
#if(Session::has('updated'))
<div class="alert alert-success">
Your settings have been updated!
</div>
#endif
<form action="{!! route('settings.update') !!}" method="post">
{!! method_field('put') !!}
{!! csrf_field() !!}
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" name="title" placeholder="Title" value="{{ config('settings.title', 'Application Title') }}">
</div>
<div class="form-group">
<label for="Facebook">Facebook</label>
<input type="text" class="form-control" id="facebook" name="facebook" placeholder="Facebook URL" value="{{ config('settings.facebook', 'Facebook URL') }}">
</div>
<div class="form-group">
<label for="twitter">Twitter</label>
<input type="text" class="form-control" id="twitter" name="twitter" placeholder="Twitter URL" value="{{ config('settings.twitter', 'Twitter URL') }}">
</div>
<input type="submit" class="btn btn-primary" value="Update settings">
</form>
#stop
As you can see, when I try to get a value from the config, I also give it a default value, just in case it has not been set yet.
You can now create different forms for different setting groups. The form action should always be the settings.update route.
When I run the app, I can see the form with the default values:
When I type some values, hit the update button and Laravel redirects me to the form again, I can see a success message and my settings that now persist in the database.
You can inject the Request class. Lets update the title:
// Injecting Illuminate\Http\Request object
public function update(Request $request, $id, Factory $cache, Setting $setting)
{
$newTitle = $request->get('title');
$cache->forget('settings');
return redirect('admin');
}
To change the value in db, then could do:
$titleSetting = App\Setting::where('name', 'title')->first();
$titleSetting->value = $newTitle;
$titleSetting->save();
The whole code looks like:
public function update(Request $request, $id)
{
$newTitle = $request->get('title');
\Cache::forget('settings');
$titleSetting = App\Setting::where('name', 'title')->first();
$titleSetting->value = $newTitle;
$titleSetting->save();
return redirect('admin');
}

Resources