Laravel 5.3: Can not access anymore the admin dashboard - php

anyone can help me here with a problem?
I'm creating one area in Laravel where Users can login accordingly to their role.
Used an artisan command to create the auth, quite straightforward so far.
Then, I started by changing the table name and the primary key of the table 'users' in the DB.
With this done, one needs to update the User Model (automatically generated by the artisan command) and let the model know where exactly is the table 'users' and which one is the primary key for that table.
protected $table = 'users';
protected $primaryKey = 'userID';
After this, once I go to the browser and do a normal login, it doesn't let me access the admin dashboard and I'm getting prompt with trying to get a property of a non-object.
This comes from the fact that once the table and the primary key are changed like I've done before, '$this' is not in object context anymore.
How can I make it work?
User.php:
class User extends Authenticatable
{
(...) public function isAdmin(){
if($this->roles->Role_Type == "Admin" && $this->is_active == 1){ //this one is the line 83 where the error is
return true;
}
return false;
}
(...)
}

You have error in this code
$this->roles->Role_Type
"$this->roles" returns the roles corresponding to that user and then you taken the field "Role_Type".
In your scenerio, there is no roles attached to that user.
So this "$this->roles" returns null.
So you could not take the value "Role_Type". This causes error.
You have to do the following
if($this->roles != null && $this->roles->Role_Type && $this->is_active == 1) {
return true;
} else {
return false;
}
Note: your code will work with has one relationship.
Class User extends Model
{
public function roles()
{
return $this->hasOne('App\Role');
}
}
If you want to use roles and permission in effecient manner, try this package https://github.com/romanbican/roles

It worked this way:
went to the DB and deleted the strong relationships (FKs) stablished between the tables, they're always a pain for Developers, requiring much more code just to have them there.
Thanks to you all for all the help and bellow is the code that used and worked fine:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
//
protected $table = 'users';
protected $primaryKey = 'userID';
protected $fillable = [
'name',
'email',
'password',
'roleID',
'photoID',
'is_active'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function role(){
return $this->belongsTo('App\Role', 'roleID');
}
public function photo(){
return $this->belongsTo('App\Photo', 'photoID');
}
// public function setPasswordAttribute($password){
//
//
// if(!empty($password)){
//
//
// $this->attributes['password'] = bcrypt($password);
//
//
// }
//
//
// $this->attributes['password'] = $password;
//
//
//
//
// }
public function isAdmin(){
if($this->role->Role_Type == "Admin" && $this->is_active == 1){
return true;
}
return false;
}
public function posts(){
return $this->hasMany('App\Post');
}
public function getGravatarAttribute(){
$hash = md5(strtolower(trim($this->attributes['email']))) . "?d=mm&s=";
return "http://www.gravatar.com/avatar/$hash";
}
}

Related

Changing the allowed fields based on user in CodeIgniter 4

I am building an inventory system where there is users with different levels of authority changing fields. I am trying to change the "protected $allowedFields" class property within a function inside the model, but it will not allow me. Do I have to create 2 different models, or bake the authentication into the html code? Any advice would be appreciated.
class InventoryModel extends Model
{
protected $table = "tcg_main_inv";
protected $primaryKey = 'id';
protected $allowedFields = ['size'];
public function setInvFields(string $userLevel)
{
if ($userLevel == "admin") {
$allowedFields = ['container_number', 'size', 'dealer_cost', 'date_in',
'sales_order_number'];
} else if ($userLevel)
$allowedFields = ['date_in', 'sales_order_number'];
}
Note: this is just a snippet of my model code.
Thank you to #ViLar, I was able to figure out a solution that seems to work. I made a function inside the model that changes the allowed fields.
class InventoryModel extends Model
{
protected $table = "tcg_main_inv";
protected $primaryKey = 'id';
protected $allowedFields;
public function userAuth(string $user_type)
{
if($user_type == "dealer"){
$this->allowedFields = [ 'container_number'];
}
else if ($user_type == "admin"){
$this->allowedFields = ['size', 'container_number', 'dealer_cost'];
}
}
}

Eloquent: guard ID when inserting into one database but don't guard it for another database.

I need to guard the ID column when inserting into a database, however I don't want to guard it when inserting into a different database due to needing to manually set the ID, so that the tables are in sync.
However I can't figure out a way to do it, below is what I have got at the moment, however this doesn't work at all as I just get an error:
Field 'id' doesn't have a default value
This is my current model:
<?php
namespace App\Models\Seasonal;
use Illuminate\Database\Eloquent\Model;
class SeasonalBanner extends Model
{
protected $connection = 'dev';
protected $guarded = [ 'id' ];
protected $appends = [ 'period' ];
public static function boot()
{
parent::boot();
self::creating(function($model){
if ($model->connection === 'live') {
$model->guarded = [];
}
});
}
public function dates() {
return $this->hasMany(SeasonalBannerDates::class);
}
public function getPeriodAttribute() {
return [ $this->start, $this->end ];
}
}
The best way in my opinion is not to use $guarded at all in such case. Just set:
protected $guarded = [];
and in your code depending on which database you use, either fill id or not.

Laravel Model without a Database?

I'm developing a system in which i have different roles for accesing. The role is present in the Users table as an integer value.
I've created a model called roles and in this model i dont need a database connection or a table. I did set some constant values representing roles matching the role field in the user table.
So what's the problem ? It seems that i can't have relations with the roles model if this hasn't a table associated in the database.
This is my roles model:
class Roles extends Model {
const ROL_ADMINISTRADOR = 1;
const ROL_DIRECTOR = 2;
const ROL_PROFESOR = 3;
const ROL_RECOPILADOR = 4;
private $rol_id;
private $roles = [
self::ROL_ADMINISTRADOR => 'Administrador',
self::ROL_DIRECTOR => 'Director',
self::ROL_PROFESOR => 'Profesor',
self::ROL_RECOPILADOR => 'Recopilador'
];
/**
* RELACIONES
*/
public function _usuarios() {
return $this->hasMany(Usuarios::class, "rol", "rol_id");
}
/**
* FORMATEADORES
*/
/**
* FUNCIONES
*/
public function nombre() {
return $this->roles[$this->rol_id];
}
}
This is my users model
class Usuarios extends Authenticatable {
use Notifiable;
const STATUS_ACTIVO = 1;
const STATUS_INACTIVO = 0;
protected $table = 'usuarios';
protected $primaryKey = 'usuario_id';
/*
* RELACIONES
*/
public function _rol() {
return $this->hasOne(Roles::class, 'rol', 'rol_id');
}
public function _perfil() {
return $this->hasOne(Perfiles::class, "usuario", "usuario_id");
}
/*
* FORMATEADORES
*/
}
But i got this error
Base table or view not found: 1146
When i try to do this
<?= Auth::user()->_rol->nombre() ?>
=========================================================================
I think i've found the solution.
I did the following changes:
1.- in the roles model I did add the constructor method and customized it
public function __construct($rol) {
parent::__construct();
$this->rol_id = $rol;
}
2.- In the users model change the method to this
public function _rol() {
return new Roles($this->usuario_id);
}
There is a thing here: if the method is called like this '_rol' the model will think is about a relation and will required a relation response so is neccesary to call it this way '_rol()' (with the parenthesis)
<?= Auth::user()->_rol()->nombre() ?>
You only need the Role model if you have another table to store the roles.
If you, instead, have the role represented as a field in the users table, you can access it just doing:
$role = $user->role;
I suggest you to use https://github.com/artesaos/defender to manage roles and permitions.

Obtaining a list of non-linked models, in many_to_many relations, using Laravel Eloquent

I have a User-Roles model, using Laravel 4 where a user can have many roles, using Eloquent. I can access all roles linked to a user easily using this code :
class User extends Model {
protected $table = 'user';
protected $fillable = array('name');
public function rolesLinked() {
return $this->hasMany('App\UserRoleLink', 'user_id');
}
}
I've been trying to obtain the roles that are not linked to a user, to display on the specific user's page in a select box. Using this function, included in the User class.
public function rolesNotLinked() {
$user = this
$roles = Roles::whereDoesntHave('App\UserRoleLink',function($query) use ($user){
$query->where('user_id',$user->id);
});
}
The problem is, calling this function gives me the following error.
Call to undefined method Illuminate\Database\Query\Builder::App\UserRoleLink()
I've tried using has with < 1 to see if the function was problematic, but after reading this and the online source code, the function call pretty much does what I've tried.
Is something wrong in my function call, or have I messed up configurations somewhere?
For reference, here are my other Model classes:
class UserRoleLink extends Model{
protected $table = 'user_role_link';
protected $fillable = array('role_id','user_id);
public function role() {
return $this->hasOne('App\Role', 'role_id');
}
}
class Role extends Model{
protected $table = 'role';
protected $fillable = array('name');
}
EDIT: I've found out that I messed up by fillables when I copy-pasted. It didn't fix the issue, but I guess that's one step closer.
To use whereDoesntHave method, you must add the relation in your Role Model.
class Role extends Model{
protected $table = 'role';
protected $fillable = array('name');
public function UserRoles() {
return $this->hasMany('App\UserRoleLink', 'id');
}
}
Also, the whereDoesntHave method first parameter is not thte model but the function of the relation:
public function rolesNotLinked() {
$user = this
$roles = Roles::whereDoesntHave('UserRoles',function($query) use ($user){
$query->where('user_id',$user->id);
});
}

Laravel4 one-to-one relationship is not loaded when in testing environment

Im currently facing this strange behaviour.
<?php
// Models
class User extends \Eloquent {
protected $table = 'user';
public $timestamps = FALSE;
public function credit() {
return $this->hasOne('Credit', 'uid');
}
}
class Credit extends \Eloquent {
protected $table = 'user_credit';
public $timestamps = FALSE;
public function user() {
return $this->belongsTo('User', 'uid');
}
}
// Service
function doThings() {
// This is always working
$credit = Credit::where('uid', $user->id)->first();
// This doesn't work in test environment, but it does outside of it, i.e. in a route
// $credit = $user->credit;
if (empty($credit)) {
$credit = new Credit();
// Set some fields... then save.
$credit->foo = 'bar';
}
$user->credit()->save($credit);
}
// Test
Service::doThings(); // <--- works as expected the first time
Service::doThings(); // <--- fails, trying to save a new record instead of updating.
// In a test route
Route::get('/test', function() {
$user = User::find(1);
Service::doThings(); // <--- works as expected
Service::doThings(); // <--- works as expected
Service::doThings(); // <--- works as expected
return 'test';
});
Problem is that when accessing the credit model via the $user->credit, in the testing environment the model is not loaded and NULL is returned regardless the presence of the item inside the database.. It works when explicitly loaded, using Credit::find().
Outside the testing env, things works as expected.
Any hint?
In your class
class User extends \Eloquent {
protected $table = 'user';
public $timestamps = FALSE;
public function credit() {
return $this->hasOne('User', 'uid');
}
}
You should use (to make a one to one relation between User <-> Credit using a custom key uid)
class User extends \Eloquent {
protected $table = 'user';
public $timestamps = FALSE;
public function credit() {
return $this->hasOne('Credit', 'uid'); // <---
}
}
So, you can query like
$credit = User::find(1)->credit;

Categories