Getting incorrect 'id' using sqlite in laravel [duplicate] - php

I am trying to use email as my table's primary key, so my eloquent code is-
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserVerification extends Model
{
protected $table = 'user_verification';
protected $fillable = [
'email',
'verification_token'
];
//$timestamps = false;
protected $primaryKey = 'verification_token';
}
And my DB is like this-
but if I do this-
UserVerification::where('verification_token', $token)->first();
I am getting this-
{
"email": "sdfsdf#sdfsdf.sdf",
"verification_token": 0,
"created_at": "2016-01-03 22:27:44",
"updated_at": "2016-01-03 22:27:44"
}
So, the verification token/primary key becomes 0.
Can anyone please help?

This was added to the upgrade documentation on Dec 29, 2015, so if you upgraded before then you probably missed it.
When fetching any attribute from the model it checks if that column should be cast as an integer, string, etc.
By default, for auto-incrementing tables, the ID is assumed to be an integer in this method:
https://github.com/laravel/framework/blob/5.2/src/Illuminate/Database/Eloquent/Model.php#L2790
So the solution is:
class UserVerification extends Model
{
// if your key name is not 'id'
// you can also set this to null if you don't have a primary key
protected $primaryKey = 'your_key_name';
public $incrementing = false;
// In Laravel 6.0+ make sure to also set $keyType
protected $keyType = 'string';
}

On the model set $incrementing to false
public $incrementing = false;
This will stop it from thinking it is an auto increment field.
Laravel Docs - Eloquent - Defining Models

Theres two properties on the model you need to set. The first $primaryKey to tell the model what column to expect the primary key on. The second $incrementing so it knows the primary key isn't a linear auto incrementing value.
class MyModel extends Model
{
protected $primaryKey = 'my_column';
public $incrementing = false;
}
For more info see the Primary Keys section in the documentation on Eloquent.

I was using Postman to test my Laravel API.
I received an error that stated
"SQLSTATE[42S22]: Column not found: 1054 Unknown column" because Laravel was trying to automatically create two columns "created_at" and "updated_at".
I had to enter public $timestamps = false; to my model. Then, I tested again with Postman and saw that an "id" = 0 variable was being created in my database.
I finally had to add public $incrementing false; to fix my API.

keep using the id
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserVerification extends Model
{
protected $table = 'user_verification';
protected $fillable = [
'id',
'email',
'verification_token'
];
//$timestamps = false;
protected $primaryKey = 'verification_token';
}
and get the email :
$usr = User::find($id);
$token = $usr->verification_token;
$email = UserVerification::find($token);

Related

Inserting a new row on Laravel using "save" method

I am studying Laravel and trying to insert a new row in my table estabelecimentos.
Why is this working to insert a new row:
$estabelecimento = Estabelecimento::create([
'nome' => $nome
]);
And this is not working? Using var_dump on save method it returns null.
$estabelecimento = new Estabelecimento();
$estabelecimento->nome = $nome;
$estabelecimento->save;
I already tried using try/catch but it doesn't throw errors, it just don't insert the row and returns null on save method.
My Class:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Estabelecimento extends Model
{
public $timestamps = false;
protected $fillable = ['nome'];
public function Comentarios()
{
return $this->hasMany(Comentario::Class);
}
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comentario extends Model
{
public $timestamps = false;
protected $fillable = ['nome', 'votes'];
public function Estabelecimento()
{
return $this->BelongsTo(Estabelecimento::Class);
}
}
Table estabelecimentos
name
type
extra
id
bigint(20)
PK - AUTOINCREMENT
nome
varchar(100)
-
save is a method and hence you call it with ().
so, replace the following line of code:
$estabelecimento->save;
with the following:
$estabelecimento->save(); // focus on `()`
Remember to always look at the documentation: https://laravel.com/docs/8.x/eloquent-relationships#the-save-method

Laravel 6: User models uses UUID instead of auto-increment. Where to update DB session logic?

OK so my User models uses webpatser/laravel-uuid. All migrations are using UUID.
So now my model looks like:
<?php
namespace App\Models;
use App\Models\Traits\Uuid;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
class User extends Authenticatable
{
use Notifiable;
use Uuid;
public $incrementing = false;
public $timestamps = true;
protected $guarded = [
'uuid',
];
protected $keyType = 'string';
protected $primaryKey = 'uuid';
protected $table = 'users';
protected $dates = [
'created_at',
'updated_at',
];
protected $hidden = [
'password',
'remember_token',
];
public function setPasswordAttribute($password): void
{
$this->attributes['password'] = Hash::make($password);
}
}
I want to use database session driver. I created session table via php artisan session:table. All migrations are done. I obviously had to rename existing user_id column. I've changed it to user_uuid. I know it's not enough as I can't find the logic responsible for populating this db table. I guess it's somewhere in the vendor (Illuminate).
Where is the logic to populate my non-default session column?
Now each open the page gives:
So I know what's the issue, what's causing it, how to change it, but I don't know where to start. Thanks for any hints.
I think you would benefit of a custom session handler because the name of the column user_id is hardcoded into the addUserInformation() method.
Extend the existing DatabaseSessionHandler.php and replace the addUserInformation() method so it looks for the correct column name:
class DatabaseUuidSessionHandler extends DatabaseSessionHandler
{
protected function addUserInformation(&$payload)
{
if ($this->container->bound(Guard::class)) {
$payload['user_uuid'] = $this->userId();
}
return $this;
}
}
Register it in one of your service providers:
class SessionServiceProvider extends ServiceProvider
{
public function boot()
{
Session::extend('databaseUuid', function ($app) {
return new DatabaseUuidSessionHandler;
});
}
}
Finally update SESSION_DRIVER in your .env to use the newly created databaseUuid driver.
Remember that this is untested code and should only be used as a guideline of how this could work.

How to load relationship with Eloquent?

I have a Link model and each link has an owner (represented by ownerId in DB, which is a foreign key of the User table).
Here is the Link model :
<?php namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;
class Link extends Model {
protected $table = "Link";
// ...
// Relationships
public function owner()
{
return $this->belongsTo(User::class, 'ownerId', 'id');
}
}
When I use $data = Link::find($linkId)->toJson(); in my LinkController, owner is included but is null in the JSON data. I also tried $data = Link::with('owner')->find($linkId)->toJson(); and $data = Link::find($linkId)->load('owner')->toJson();
And when I use $data = Link::find($linkId)->owner->toJson();, I get the user data. Is there something missing in my code?
Is there a way to load the owner in the link object and to get it via JSON without additional requests / steps ?
I finally found the issue. The primary key in my User table was not standard (it was a string key instead of int).
I added the following lines in my User model :
public $incrementing = false;
public $keyType = 'string';
And now $data = Link::with('owner')->find($linkId); is just working fine.

Laravel One-to-One relationship not working

I have 2 database tables => mobile_phones , mobile_users
Schema for mobile_phones
phone_id (primary key , auto_increment)
phone_name (varchar(150))
phone_model (int (11))
Schema for mobile_users
user_id (primary key , auto_increment)
username (varchar(150))
mobile_phone_id (foreign key referencing mobile_phones(phone_id))
Model class for mobile_phones
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class MobilePhone extends Model
{
protected $primaryKey = "phone_id";
public $timestamps = false;
protected $table = "mobile_phones";
protected $fillable = array("phone_name","phone_model");
public function mobileUser()
{
return $this->hasOne("MobileUser","mobile_phone_id");
}
}
Model class for mobile_users
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class MobileUser extends Model
{
protected $primaryKey = "user_id";
public $timestamps = false;
protected $table = "mobile_users";
protected $fillable = array("username","mobile_phone_id");
public function mobilePhone()
{
return $this->belongsTo("MobilePhone","phone_id");
}
}
I am trying to establish One-to-One relationship between MobileUser and MobilePhone models but it isn't happening. Below is my code in Controller's action -
public function query()
{
$getUsername = MobilePhone::find(1)->username;
echo $getUsername;
}
The above code gives me NULL when I do a var_dump()
I did check similar questions on SO and they used with() (but this isn't necessary). I am referring Laravel 5.2 docs and they state that we can access relate record in another relation using Eloquent's dynamic properties. Link to that docs is here
Please Help !!
You need to call the function of your model so do the following
public function query()
{
$getUsername = MobilePhone::find(1)->mobileusers;
echo $getUsername->username;
}
When doing this:
public function query()
{
$getUsername = MobilePhone::find(1)->username;
echo $getUsername;
}
You try to access a username property out of a MobilePhone number, which is incorrect.
Try this:
public function query()
{
$getUsername = MobilePhone::find(1)->mobileUser->username;
echo $getUsername;
}
Also I encourage you to use the with statement as it will preload all dependencies needed (means 1 single query) instead of eager loading it (many queries)
Something like this :
public function query()
{
$getUsername = MobilePhone::find(1)->mobileUser;
echo $getUsername->username;
}

Special UUID primary key for laravel eloquent

I have a users table that doesn't use an auto increment primary key, instead it uses a binary uuid primary key. I set up my custom model to interact with my table however, I'm having trouble trying to find records by using ::find() because for a case like this, this uuid needs to searched by using HEX() and UNHEX() mysql functions. How to I override this and have whatever is in ::find() to be hexed. The name of the model is Player.
So if I was to try to find a user with a uuid of 9d823b9eec224cbea10b69bec2c5adef, I cannot find them by doing:
Player::find('9d823b9eec224cbea10b69bec2c5adef') since the uuid needs to be unhexed.
I've tried Player::find("UNHEX('9d823b9eec224cbea10b69bec2c5adef')"); with no results.
Here's my model so far:
class Player extends Eloquent {
protected $table = 'players';
protected $connection = 'game';
protected $primaryKey = 'uuid';
public $incrementing = false;
public $timestamps = false;
}
The datatype for uuid is binary(16)
Update
I've got it to work by using Player::find(DB::raw("UNHEX('9d823b9eec224cbea10b69bec2c5adef')")); however this is a lot to write every time I need to look up a user.
Is there any way I can have the parameter for ::find() always run through DB::raw("UNHEX('uuid')") or be passed through the function hex2bin()?
I am 100% certain I will always be using UUID so I want to override ::find(), not create a new method.
I would try to unhex it in PHP prior to passing it to mysql:
Player::find(hex2bin('9d823b9eec224cbea10b69bec2c5adef'));
You could add this method to your Player class:
public static function findUUID($uuid) {
return self::find(hex2bin($uuid));
}
Now any where in your project you can call it like:
$result = Player::findUUID('9d823b9eec224cbea10b69bec2c5adef');
If you do not want to declare it statically you can:
public function findUUID($uuid) {
return self::find(hex2bin($uuid));
}
and then reference it in your code with:
$result = new Player;
$result->findUUID('9d823b9eec224cbea10b69bec2c5adef');
This should allow you to override the native find() behavior and not have to use findUUID() instead:
protected $primaryKey = 'uuid';
public static function find($uuid)
{
return parent::find(hex2bin($uuid));
}
If you really want it like that, you can also do Player::find('9d823b9eec224cbea10b69bec2c5adef') with this
class Player extends Eloquent {
protected $table = 'players';
protected $connection = 'game';
protected $primaryKey = 'uuid';
public $incrementing = false;
public $timestamps = false;
public static function find($uuid, $columns = array('*')) {
return self::find("UNHEX('$uuid')", $columns);
}
}
EDITED
added self, as user Elliot Fehr suggested

Categories