Is it possible to define primaryKey on runtime for Laravel / Eloquent? - laravel

In Eloquent, I know it's possible to define the table on runtime with $model->setTable().
I tried adding a new item in the constructor like:
$myModel = new \MyModel(array(), 'my_primary_key');
$myModel->setTable('mytable');
with the constructor being:
class MyModel extends Eloquent {
public function __construct($attributes = array(), $primaryKey = 'id') {
parent::__construct($attributes); // Eloquent
$this->primaryKey = $primaryKey;
}
}
That makes my $primaryKey = 'id' like the default.
- This one doesn't work cause it doesn't change the primaryKey to whatever I define in my call the constructor, it just gets the default ('id'). If I don't set a default I get the following error:
Missing argument 3 for MyModel::__construct(), called in
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 517 and defined
I also tried:
$myModel->setAttribute('primaryKey', 'my_primary_key');
But this one doesn't set the attribute
But nothing works. The default for Laravel is having 'id' as the primaryKey, but in my tables I have things like 'car_id' for table Cars, and so on, so I get errors like:
Column not found: 1054 Unknown column 'id' in 'where clause'
(SQL: select * from `cars` where `id` = 1 limit 1)
I tried to look into the code: https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php#L1415, but it doesn't have a method to set it on runtime.

Related

Laravel updateOrCreate ignores 1 field

I have the following updateOrCreate:
protected $fillable = ['type', 'token', 'expires_on'];
$access = Ebaytoken::updateOrCreate(
['type' => 'access_token'],
['token' => $request->access_token, 'expires_on' => $request->access_token_expires_on]
);
However it gives this error:
SQLSTATE[23000]: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Cannot insert the value NULL into column 'type', table 'toolkit.dbo._ebaytokens'; column does not allow nulls. INSERT fails. (SQL: insert into [_ebaytokens] ([token], [expires_on], [updated_at], [created_at]) values (access token goes here, 2020-03-09 09:01:02, 2021-07-12 14:18:31.031, 2021-07-12 14:18:31.031))
It's ignoring the type column in my query.
What have I done wrong here?
You have defined your own constructor on your model which is not its default constructor it gets from the Model class. The constructor on Model takes the attributes as an array and fills them on the instance. This way you can create a new instance of a Model with attributes. This is the important part of that constructor:
public function __construct(array $attributes = [])
{
...
$this->fill($attributes);
}
Without that you wouldn't be able to create a new Model instance with attributes filled.
This is what updateOrCreate is doing:
public function updateOrCreate(array $attributes, array $values = [])
{
return tap($this->firstOrNew($attributes), function ($instance) use ($values) {
$instance->fill($values)->save();
});
}
It is retrieving by the attributes or creating a new instance with the attributes (first argument). Eventually down those method calls you get to Model::newInstance which is doing this:
$model = new static((array) $attributes);
So without that constructor it can't create that new instance of the Model with those attributes, which in this case because of calling updateOrCreate is the first array you pass to updateOrCreate. It can fill the instance with the second array though as that is just a call to fill on the Model instance.
I would suggest to not override the constructor on a Model but if you really need to you could show what you are trying to do and perhaps you could get some advice or ideas on how to go about it.

custom primary key in Laravel not working

I've set a custom primary key in my Task.php model.
class Task extends Model
{
//
protected $primaryKey = 'taskn';
public $incrementing = false;
}
I've also set taskn as my primary key in the migration:
$table->string('taskn');
$table->primary('taskn');
But I still get the error
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause' (SQL: select * from `Task` where `id` = 1 limit 1)
For some reason Laravel still tries to query id.
I am trying to retrieve the data with the following call:
$tasks = DB::table('tasks')->find($taskn);
What is wrong here?
I'm doing $tasks = DB::table('tasks')->find($taskn);
Here's your problem.
DB:: calls don't use Eloquent - you're completely bypassing it. If you do Task::find($taskn) it'll work, but DB:: calls have no idea about your $primaryKey settings.

Column not found laravel 5.4

I get the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'books.id' in
'where clause' (SQL: select * from books where books.id =
98745632564 limit 1)
when I pass id value as id. I have column name bookID in my database but in the above error it is comparing books.id = 98745632564. I could not understand where book.id is coming from.
public function showBook($id){
$book = Book::findOrFail($id);
return $book;
}
The code works perfectly fine when I pass id value with the query as follows
public function showBook($id){
$book = Book::where('bookID', $id)->find();
return $book;
}
You should set:
protected $primaryKey = 'bookID';
in your Book model to make:
$book = Book::findOrFail($id);
version work.
Methods find or findOrFail are using primary key and this is by default set to id, so if you have any custom primary key, you should set it in your Eloquent model.

How to update field in table Laravel or create?

I try to update field rate in table by primary key user_id.
So, I need to increment of decrement rate field. If row is not exist I need to create it.
I tried:
$this->point = -1; // Or $this->point = 1;
Rating::updateOrCreate(["user_id", $id], ["rate" => $this->point]);
But it does not work:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '0' in 'where clause' (SQL: select * from `rating` where (`0` = user_id and `1` = 5) limit 1)
This is because your passing the column and the value as two separate values.
Change:
["user_id", $id]
to:
["user_id" => $id]
Hope this helps!
Laravel (eloquent) provides a fluent way to update related models.
Assuming the following model structure:
Rating.php
public function user()
{
return $this->belongsTo('App\User');
}
User.php
public function ratings()
{
return $this->hasMany('App\Rating');
}
You can easily update the relation via associate()
$user = User::findOrFail($userId);
$rating = Rating::findOrFail($ratingId);
$rating->user()->associate($user)->save();
Read more about Relationships in Eloquent

Simple find command won't work. Error shows wrong foreign key

I'm trying to edit the content of a Message that already exists. So when I click:
{{ HTML::linkAction('MessageController#edit', 'edit', array($message->PK_message)) }}
My 'MessageController'
public function edit($id)
{
$message = Message::find($id);
dd($message);
// return Redirect::back();
}
I get this error message:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'tblMessages.id' in 'where clause' (SQL: select * from `tblMessages` where `tblMessages`.`id` = {messages} limit 1)
What attracts my attention is that 'tblMessages.id' is not my Foreign key.
So I think there's the problem?
Can I pass a custom Foreign key or is there another problem?
When you use a different Primary Key other than id then you should explicitly declare the $primaryKey property like this:
class Message extends Model {
// This is required now
protected $primaryKey = 'PK_message';
}
By default, Laravel assumes (when not declared explicitly) id as primary key.

Resources