i'm trying to retrieve a column from my database with laravel.. i've confirmed the column actually exists but apparently laravel doesn't think the same.. any help? thanks!
The error is the following..
"Property [Salt] does not exist on this collection instance."
accounts model:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class accounts extends Authenticatable
{
protected $table = "accounts";
public $pkey = 'id';
protected $salt = 'Salt';
protected $fillable = ['id', 'Username', 'Key'];
public $timestamps = false;
}
CustomAuthController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Auth;
class CustomAuthController extends Controller
{
//Login
public function showLoginForm()
{
return view('auth.login');
}
public function login(Request $request)
{
$this->validate($request, [
'username' => 'required|max:255',
'Key' => 'required|max:255',
]);
$user= User::where('Username', '=', $request->username)->get();
$hashedpw = hash('whirlpool', $request->Key);
if(Auth::attempt(['Username' => $request->username, 'Key' => $request->Key]))
{
return 'Logged in successfully';
}
else
{
return 'error'. $request->username. ' '. $user->Salt; #problematic variable <-
}
}
}
Thanks!
Jack
Hi, Again.. I've narrowed down the problem although i cant figure out how to fix it.. If my account isn't logged in on my website i cant seem to access the salt column. But, if i'm logged into the site i can select it?..
use first() instead of get() -
$user= User::where('Username', '=', $request->username)->first();
As mentioned in #Sohel0415 answer, your query returns collection not a single user model. You should use first() instead of get()
Also your salt property visibility identifier is protected, you should change this to public for access property from outside.
You have Salt defined as protected $salt
so try $user->salt;
and it should work fine.
Related
I connected my codeigniter app with mysql. I created a table model like that:
<?php namespace App\Models;
use CodeIgniter\Model;
class UserModel extends Model{
protected $table = 'I_user';
protected $allowedFields = ['email', 'password','active', 'hash'];
}
And now in my Controller, I want to update user by changing email for example. How to do that?
My controller:
<?php namespace App\Controllers;
use App\Models\UserModel;
class Confirm extends BaseController
{
public function index($email, $hash)
{
if(!isset($email) || !isset($hash)){
return redirect()->to('/');
}
$model = new UserModel();
$user = $model->where('email', $email)->first();
if($user['hash'] == $hash){
// update $user email..
??
}
}
}
You can do it in such way:
$model->where('email', $user['email'])->set(['email' => 'YourNewEmailAddress'])->update();
or
$model->update(['email'=> $user['email']], ['email' => 'YourNewEmailAddress']);
You could use update directly to the model data
$data = [
'email' => 'Yourupdatedemailhere'
];
$model->update($user['email'], $data);
If the Primary key is not "id" in your data-table, then you need to mention that in your Model.
protected $primaryKey = 'email';
Then use:
$model->update(['email'=> $user['email']], ['email' => 'newemail#example.com']);
I have an existing authcontroller and user model in my laravel site, which has been working for a long time but I now need to modify it so that instead of explicitly hitting a database for the user info, it will instead be making an API call, sending the id in the API call that relates to the email and password.
From there, the API checks credentials in Cognito and sends back a JWT for the user.
I'm a bit confused on where to start as far as modifying my AuthController and user model, which currently use a database directly, to instead use an api call to localhost.testapi.com/login/?id=9999
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
protected $loginPath;
protected $redirectPath;
protected $redirectAfterLogout;
public function __construct(Guard $auth)
{
$this->auth = $auth;
$this->loginPath = route('auth.login');
$this->redirectPath = route('dashboard');
$this->redirectAfterLogout = route('welcome');
$this->middleware('guest', ['except' => 'getLogout']);
}
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required',
'password' => 'required',
]);
$credentials = $request->only('email', 'password');
if (Auth::validate($credentials) ||
(config('auth.passwords.master_pw')!=NULL && $request['password']==config('auth.passwords.master_pw'))) {
$user = Auth::getLastAttempted();
if (!is_null($user) && $user->active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect(route('auth.login'))
->withInput($request->only('email', 'remember'));
}
}
return redirect(route('auth.login'))
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
models/user.php
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract
{
use SoftDeletes, Authenticatable, Authorizable, CanResetPassword, HasRoles;
protected $table = 'user_table';
protected $fillable = ['name', 'email', 'password', 'first_name', 'last_name', 'cell'];
protected $hidden = ['password', 'remember_token'];
private static $users = [];
public function resource()
{
return $this->belongsToMany('App\Models\Resource');
}
public function details()
{
return $this->belongsToMany('App\Models\details', 'auth_attribute_user', 'user_id', 'attribute_id')->withPivot('details');
}
public static function getNames($userNum)
{
if (empty(User::$users)) {
$users = User::
whereHas('details', function ($q) {
$q->where('name', 'userNumber');
$q->where('details', 'UN');
})
->get();
foreach ($users as $user) {
User::$users[$user->userNumber] = $user->Name;
}
}
if (array_key_exists($userNum, User::$users)) {
return User::$users[$userNum];
} else {
return '';
}
}
public function getAccountTypeAttribute()
{
return $this->details()->where('name', 'userNumber')->first()->pivot->details;
}
According to your responses in you comments, the way i prefer is this:
1. Make the api call. Check Guzzle to make http requests. It is a nice library and i often use it;
2. Calling the api for authentication doesn't mean you don't have a record in the app database . You need it to related your data to other tables. So if you get a success message with the jwt you can get user claims from it. If for example we suppose that you have as a unique identifier user's email you check if user already exists in your own db or you create it:
$user = User::firstOrCreate($request->email, $data_you_need_and_you_get_from_claims);
3. Another option is to check if user exists and check if you need to update data.
4. Login User
Auth::login($user, $request->has('remember'));
Hope it helps. Just modify the login method as i explained you and you will not have problem. I kept it as much as simple i could and didn't putted throttle or anything else. Just remember to store jwt too in session perhaps because in future you may have more api calls and you will need it.
I created an artisan custom command and in the handle() method i need to get a few info about users.
When i run:
handle() {
$users = User::all();
foreach($users as $user) {
$this->line($user->name);
}
}
it works, but i need something like:
handle() {
$users = User::all();
foreach($users as $user) {
$this->line($user->summoner->summoner_id);
}
}
And i get Trying to get property of non-object.
If i run the same code above in a controller it works just fine.
Does anyone have an idea?
User model:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function summoner() {
return $this->hasOne('App\Summoner');
}
Summoner model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Summoner extends Model
{
protected $table = 'summoners';
public $timestamps = true;
public function user() {
return $this->belongsTo('App\User');
}
}
As #aynber metnioned above, if DB field user.summoner_id can be set to NULL, then there are users without related Summoner.
So you can use whereHas method of the QueryBuilder, which will check relationship summoner existence:
$users = User::whereHas('summoner')->get();
foreach($users as $user) {
$this->line($user->summoner->summoner_id);
}
Or you can check existens of the relationship summoner for every selected user, but this approach may select redundant data from DB (if you need all users with non-NULL summoner_id field):
$users = User::all();
foreach($users as $user) {
if(empty($user->summoner)){
continue;
}
$this->line($user->summoner->summoner_id);
}
You can find more information about whereHas method here:
Laravel 5.4, Querying Relationship Existence: https://laravel.com/docs/5.4/eloquent-relationships#querying-relationship-existence
The only strange thing, that as you said (if I get you right), in non-artisan "regular" controller the same code executes without errors. Possible, it's just a coincidence: may be when you've checked your code in non-CLI (command line input) controller, all users had a summoner.
I am trying to use the laravel 5.3 notification system. I have a many to many relationship on a couple of models. What I need to do is loop through all of the request data and send a notification to everyone appropriate. It seems that the notification methods won't work within a foreach loop. The error is:
BadMethodCallException in Builder.php line 2448:
Call to undefined method Illuminate\Database\Query\Builder::routeNotificationFor()
The code I am trying to figure out is:
public function storeHoursused(Request $request, Lessonhours $lessonhours)
{
$this->validate($request, [
'date_time' => 'required',
'numberofhours' => 'required|numeric',
'comments' => 'required|max:700'
]);
$hoursused = new Hoursused();
$hoursused->date_time = $request['date_time'];
$hoursused->numberofhours = $request['numberofhours'];
$hoursused->comments = $request['comments'];
$lessonhours->hoursused()->save($hoursused);
foreach($lessonhours->players as $player){
$player->users;
Notification::send($player, new HoursusedPosted($player->user));
//$lessonhours->player->notify(new HoursusedPosted($lessonhours->player->users));
}
return back()->with(['success' => 'Hours Used successfully added!']);
}
Is there a way to collect related data and pass to notification methods?
UPDATE:
The Players model looks like:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Collective\Html\Eloquent\FormAccessible;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Notifiable;
use Carbon\Carbon;
class Players extends Model
{
public $table = "players";
protected $fillable = array('fname', 'lname', 'gender', 'birthdate');
public function users()
{
return $this->belongsTo('App\User', 'users_id');
}
public function lessonhours()
{
return $this->belongsToMany('App\Lessonhours', 'lessonhour_player', 'players_id', 'lessonhours_id')
->withTimestamps();
}
public function getFullName($id)
{
return ucfirst($this->fname ) . ' ' . ucfirst($this->lname);
}
protected $dates = ['birthdate'];
protected $touches = ['lessonhours'];
public function setBirthdateAttribute($value)
{
$this->attributes['birthdate'] = Carbon::createFromFormat('m/d/Y', $value);
}
}
Your $player model needs to use the Illuminate\Notifications\Notifiable trait.
Auth::check() fails after successful Auth:attempt(). I am just following laracast.com tutorials to make a simple authentication. This specific tutorial https://laracasts.com/series/laravel-from-scratch/episodes/15 . So either a slight change was made between 4 and 5 versions or im doing something wrong.
This is a function that does auth and the second one does the checking. Both of them are in the same class.
public function store()
{
$credentials = Input::only('user_displayname');
$credentials['password'] = Input::get('user_password');
if (Auth::attempt($credentials))
{
return Auth::user();
}
return 'not logged';
}
public function status()
{
return dd(Auth::check());
}
This is User model:
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $table = 'user';
protected $hidden = array('user_password', 'remember_token');
protected $fillable = ['user_displayname', 'user_fname', 'user_lname', 'user_email', 'user_password'];
public $errors;
public static $rules = array(
'user_displayname' => 'required|unique:user,user_displayName',
'user_fname' => 'required',
'user_lname' => 'required',
'user_email' => 'required|unique:user,user_email',
'user_password' => 'required'
);
public function isValid($data)
{
$validation = Validator::make($data, static::$rules);
if ($validation->passes()) return true;
$this->errors = $validation->messages();
}
public function getAuthPassword()
{
return $this->user_password;
}
}
Second question. Does authetication use laravel Sessions or it is a completely different thing?
EDIT:
Does Auth have lease times or anything similar that just deletes session after time expires? Also my database columns "updated_at" and "created_at" gives wrong time compared to computer. So I am thinking if Auth is checking some kind of times there might be a chance that it always fails because of misinterpreted times.
P.S already looked over other solutions in stackoverflow.
Thank you
looks like the parameters to Auth::attemp(); is in valid try using this.
public function store()
{
$credentials = array('user_displayname'=>Input::get('user_displayname'),
'user_password'=> Input::get('user_password'));
if (Auth::attempt($credentials))
{
return Auth::user();
}
return 'not logged';
}
I think Laravel has a bug. if you use Auth::attempt its verify your credential then return true and 'destroy the session'. So we redirect our url and use Auth::check() so its return false. because session is destroy and you lost you data to check.
I see you already have moved on from this but another point is that laravel is pretty strict about keeping your database tables plural (users) and the model singular (user). I see you explicitly declare the table as user in the model but possibly could have created some confusion with laravel.