Custom Model and fields with Sentinel / Laravel - php

I', integrating a new system to an existing database.
So, my User table doesn't have default fields names.
All names are in spanish, so, Sentinel looks for email when he should look for "correo"
Also, when executing
Sentinel::check(),
I get this message error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'administrador.id' in 'where clause' (SQL: select * from `administrador` where `administrador`.`id` = 1 and `administrador`.`deleted_at` is null limit 1)
In fact, id doesn't exists, the PK is called administradorid
The only resource I found is a very quick one:
https://github.com/cartalyst/sentinel/wiki/Extending-Sentinel
It says it is extremly easy, but do not mention this case.
So, basically, how can I customize all the fields name of the Sentinel Model???
Here is my model:
class Administrador extends EloquentUser {
protected $table = 'administrador';
protected $fillable = [];
protected $guarded = ['administradorid'];
protected $hidden = ['contrasena', 'remember_token'];
use SoftDeletes;
protected $dates = ['deleted_at'];
}
Any help will be appreciated!

First, the id issue is a basic Laravel Eloquent issue. If the primary key for your model is not id, then you need to set the $primaryKey property on your model to the correct field name. Additionally, if your primary key is not an autoincrementing integer, then you need to set the $incrementing property to false, as well.
For the email issue, that is a Sentinel specific issue. The EloquentUser class has a $loginNames property that is set to an array of valid field names that contain user logins. The default is just ['email'], so you need to override this property and change it to your field name.
So, your Administrador class ends up looking like:
class Administrador extends EloquentUser {
use SoftDeletes;
protected $table = 'administrador';
protected $primaryKey = 'administradorid';
//public $incrementing = false; // only if primary key is not an autoinc int
protected $fillable = [];
protected $guarded = ['administradorid'];
protected $hidden = ['contrasena', 'remember_token'];
protected $dates = ['deleted_at'];
// Sentinel overrides
// array of fields that hold login names
protected $loginNames = ['correo'];
}

Related

Laravel eloquent HasMany type error at include in controller

I have a Customer model with many Loans records related by idecli Varchar field in both tables.
class Customer extends Model
{
use HasFactory;
protected $table = 'tblcli';
protected $primaryKey = 'idecli';
public function loans() {
return $this->hasMany(Loan::class,'idecli','idecli');
}
class Loan extends Model
{
use HasFactory;
protected $table = 'tblmca';
protected $primaryKey = 'ide';
public function customer(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Person::class,'idecli', 'idetrc');
}
}
The type of idecli field is varchar, however, eloquent retrieves that column as type Integer. I assume that it assumes the type by the content of the column that contains numbers inside a varchar.
In such a way that when retrieving the relationship, it generates a type error in the SQL query.
If I perform the query through an SQL tool, postgres returns a Varchar, but it seems that Eloquent transforms it into an Integer.
$customers = Customer::where('salcli','>',0)
->with('loans')
->paginate($perPage);
And error:
{
"message": "SQLSTATE[42883]: Undefined function: 7 ERROR: el operador no existe: character varying = integer\nLINE 1: select * from \"tblmca\" where \"tblmca\".\"idecli\" in (63282672,...\n ^\nHINT: Ning\u00fan operador coincide en el nombre y tipos de argumentos. Puede ser necesario agregar conversi\u00f3n expl\u00edcita de tipos. (SQL: select * from \"tblmca\" where \"tblmca\".\"idecli\" in (63282672, 63484298, 91003258, 1001871607, 1005461867, 1006407380, 1095809492, 1098737988, 1098801653, 1102366442))",
"exception": "Illuminate\\Database\\QueryException",
Laravel eloquent assumes that the primary key is numeric, since it is necessary to inform the model that the key is type string type. Works fine!
class Customer extends Model
{
use HasFactory;
use EloquentJoin;
protected $table = 'tblcli';
protected $primaryKey = 'idecli';
protected $keyType = 'string';
...
}

Laravel - Model ID guarding

Say we have a Topic submission html form which uses the following input fields names:
name
text
At the controller level we may have written something like this:
public function create(Request $request) {
// Validation logic ...
Topic::create($request->all());
}
What if a client user add an id input field:
id
name
text
Will Laravel populate also the id field of the new Model object?
Can I guard the id of a Model, or should I use $request->only()?
You do not need to use $fillable array or $guarded for primary key which is id by default. Eloquent will not populate primary key when you're using create() method.
Laravel has two ways of achieving this:
class Topic extends Model {
protected $fillable = [
"name" , "text"
];
}
Alternatively there is the opposite:
class Topic extends Model {
protected $guarded = [ "id" ];
}
$fillable contains what is allowed to be mass assigned (via fill or the constructor etc) in the model and $guarded contains what should never be mass assigned.
More info at https://laravel.com/docs/5.5/eloquent#mass-assignment

Laravel 5 update without id

I have a problem in Laravel 5. When I update a record in database, I get error Unknown column 'id' in 'where clause'. In the controller, I use WHERE clause to get the record I want to update. My primary key is not id and the type is bigInteger. I've tried adding protected $primaryKey in the model but it doesn't work for bigInteger. Is there any way to use my own primary key instead of using id?
Controller
$item = Item::where('item_id','=',$item_id)->first();
$item.name = $name;
$item.type = $type;
$item.save();
pls add this line to your Item.php model
class Item extends Model {
// add this line only
protected $primaryKey = 'item_id';
//..... the rest of your model
since your using custom id name, laravel will not know what is your primary key without you specify it
Laravel's orm $primaryKey default is 'id'.
When orm update, it use the sql like:
... where {$this->primaryKey} = {$this->{$this->primaryKey}}
So when you class extends orm.
You should redefine protected $primaryKey = '<your_table_primary_key>';.
Try this $item = Item::where('item_id', $item_id)->first(); If still don't working add also protected $primaryKey = "item_id"; to your model

Laravel: static::create vs DB:insert

If I use the following code snippet in my model it inserts the data:
$instance = DB::table('users')->insert(compact('email', 'username'));
But if I do this instead:
$instance = static::create(compact('email', 'username'));
It inserts null, but created_at and updated_at are inserted.
Laravel's created_at/updated_at are part of Illuminate\Database\Eloquent\Model. A raw DB::table query builder isn't an Eloquent model and thus doesn't have those automatic parameters.
NULL data is being inserted in the Eloquent query because Eloquent has a $fillable parameter you need to define. This parameter sets which columns can be mass-assigned. Laravel strips attributes not in this array when you do a fill, create, or otherwise instantiate a new object. In your model, you'd want:
class User extends Eloquent {
protected $fillable = ['email', 'username'];
}
ceejayoz answer is great, here's an explanation of how to call the model. Once the model is created, let's say this model:
class User extends Eloquent {
protected $fillable = ['email', 'username'];
}
Then you need to call by using the model directly and eloquents ORM like so:
// example is this. True method is TableName->ColumnName = Value;
$user = User::find($id);
$user->username = '';
$user->fullname = '';
$user->save();
The save will update the columns based on what you describe. With this you don't even need the fillable variable.
Some other variables for models that are good to know is:
protected $primaryKey = 'userid'; #if you have an primarykey that isn't named id
protected $table = 'tablename'; #if table name isn't pulling by the name of the model
protected $timestamps = true; #bool value, whether u have timestamp columns in table
You said us that you done
class User extends Eloquent {
protected $fillable = ['email', 'username'];
}
however in your comment you told us you got the following error in your apache log
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ''
for key 'users_email_unique' (SQL: insert into ``users
(updated_at, created_at``) values (2015-01-06 21:52:35, 2015-01-06 21:52:35))
Make sure to also include users_email_uniquein your fillable array if you want to set it.
class User extends Eloquent {
protected $fillable = ['email', 'username', 'users_email_unique'];
}

Storing and Fetching more than one table from a Single Model

Here is my Model
<?php
class VehicleModel extends Eloquent
{
protected $primaryKey = 'AutoID'; # to change the primary key else laravel will consider id as primary key
protected $table = 'vehicle';
}
Using this i can fetch
$vehiclelist = VehicleModel ::all();
But i need to fetch another table from the same model
Is it possibel to have something like this
<?php
class VehicleModel extends Eloquent
{
protected $primaryKey = 'AutoID'; # to change the primary key else laravel will consider id as primary key
protected $table = 'vehicle';
protected $secondtable = 'route';
}
And should be accessible by
$routelist= Detail::make(VehicleModel ::$secondtable );// This is the thing i am doing wrong
Is it possible in this way if not how can i do this so that i should be able to fetch the details from same model .
Note :
I can't create seperate model for each table because i need to fetch many (different) tables for each form
If you have multiple tables that are different things (not multitable inheritance) you really should create a model for each table. It isn't that much work but will make things a lot easier.
For the following example, let's assume that one vehicle can have many routes. And in the database you VehicleID in the route table referencing AutoID in the vehicle table.
Then you can add these two relations inside your models
VehicleModel
public function routes(){
return $this->hasMany('RouteModel', 'VehicleID');
}
RouteModel
public function vehicle(){
return $this->belongsTo('VehicleModel', 'VehicleID');
}
Now here are some examples how to use it:
$vehicle = VehicleModel::find(1);
$routesOfVehicle1 = $vehicle->routes;
$route = RouteModel::find(1);
$vehicleOfRoute1 = $route->vehicle;
$allVehiclesIncludingTheirRoutes = VehicleModel::with('routes')->get();
For more information, read the Laravel Docs on Relations
Why don't you extend VehicleModel class?
I think there is no way except extend.
<?php
class VehicleModel extends Eloquent
{
protected $primaryKey = 'AutoID'; # to change the primary key else laravel will consider id as primary key
protected $table = 'vehicle';
}
class RouteModel extends VehicleModel
{
protected $table = 'route';
}
class StuffModel extends VehicleModel
{
protected $table = 'stuff';
}
?>

Categories