Laravel: static::create vs DB:insert - php

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'];
}

Related

Laravel 5.6 Eloquent integrity constraint violation when saving quiz record

I'm currently working on a quiz application with Laravel 5.6 and am having trouble with saving a new quiz record.
The two tables that are being inserted into are quizzes and user_quizzes. The quizzes table contains some basic quiz data such as:
quiz_name
quiz_description
quiz_pin
active
The user_quizzes table contains two foreign keys to reference which quiz belongs to a particular user.
user_id
quiz_id
The error is an integrity constraint violation when inserting into the user_quizzes table. It successfully inserts the quiz_id but the user_id is left as NULL. I am unsure how to ensure the user_id is also inserted as I'm using Eloquent.
The full error is:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null (SQL: insert into `user_quizzes` (`quiz_id`, `user_id`) values (6, ))
I am making use of the QuizController, Quiz Model and User Model for saving the record. Here is my store() method in the QuizController:
public function store(Request $request)
{
$validator = $request->validate([
'quiz_name' => 'required|max:30',
'quiz_description' => 'required|max:500'
]);
$quiz = new Quiz(
[
'quiz_name' => $request->get('quiz_name'),
'quiz_description' => $request->get('quiz_description'),
'active' => '0',
'quiz_pin' => '5555', // hard coded for now
]
);
$quiz->save();
$user = new User;
$user->quizzes()->save($quiz);
return redirect()->route('quiz_host.dashboard.manage-quizzes')->with('quizCreated', 'Whoa ' . Auth::user()->username . ', you have created a quiz! Now it\'s time to add some questions');
}
My User Model is a follows:
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function activation()
{
return $this->hasOne('App\Models\Activation');
}
public function profile()
{
return $this->hasOne('App\Models\Profile');
}
public function quizzes()
{
return $this->belongsToMany(Quiz::class, 'user_quizzes', 'user_id', 'quiz_id');
}
}
and my Quiz model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Quiz extends Model
{
protected $table = 'quizzes';
protected $fillable = ['quiz_name', 'quiz_description', 'active', 'quiz_pin'];
public function user()
{
return $this->belongsToMany(User::class, 'user_quizzes', 'quiz_id', 'user_id');
}
}
Any guidance as to what I'm doing wrong would be greatly appreciated.
Reviewing your code
This is your controller:
QuizController.php
public function store(Request $request)
{
// your validations.
// Storing the quiz.
$quiz->save();
// User instance.
$user = new User;
// Storing the relationship.
$user->quizzes()->save($quiz);
// Returning the view.
return redirect()->route('quiz_host.dashboard.manage-quizzes')->with('quizCreated', 'Whoa ' . Auth::user()->username . ', you have created a quiz! Now it\'s time to add some questions');
}
Now, the problem here is related to the $user object.
When you do this:
$user = new User;
You are createing an instance of the User class, but this object isn't persisted yet into the database, what this means is that this object doens't have an id yet. You can confirm this doing dd($user->id), this will return null.
That's why when you do this:
$user->quizzes()->save($quiz);
It throws the SQL error, because you are calling a method to store the $primaryKey (id) of the $user object in the pivot table. But given that the $user object doens't have a primary key is trying to store a null value instead.
Solution
Now, I don't really know what is your "use case", but I will assume that the $user is the logged-in one, so to relate properly the relationship replace this:
// creating a User instance.
$user = new User;
with this:
// Logged-in user.
$user = auth()->user();
This will use the auth facade to get the actual logged-in user and return the object. Given that is a registered user it will have a proper id.
Alternative
If your use case is different and you will relate the quiz to a different user, do this instead:
// Some other user
$user = User::find($someId); // $user = User::find(5); for example
or this, to create a completely new User instance and relating a quiz to it:
// A new User
$user = new User;
$user->fill($someData);
$user-save(); // this will assign a primary key (id) to the object.
Now you can attach the related model to it.
Side note
Your users m--------m quizzes is a many to many relationship.
So, as the documentation says, the proper way to store a relatioship between the two objects is the attach() method:
$user->quizzes()->attach($quiz->id);
This method will create a record in the intermediate table (pivot) with the ids of the $user and $quiz objects.
To make it clear, new User will only create user model object, it is still not committed to DB.
When we try to call $user->quizzes()->save($quiz) it is will try to add an entry in user_quizzes pivot table, but user_id is empty, because user is still not created.
So you have to create a user entry in DB by calling $user->save() before adding it to pivot table.
$quiz->save();
$user = new User;
$user->save();
$user->quizzes()->save($quiz);

Laravel 5.3 Eloquent Model Relationship not working, Returns NULL

I am new to Laravel and am struggling with this:
Database - MSSQL existing DB schema cannot be modified as other software depends on it. (not sure if this is a problem or not)
Model/Table setup:
INFO_ALL Table - ID is primary key
PERSON Table - ID is foriegn key
ID's are hex values and I notice eloquent removes the 0x from the start of the value and am not sure if this is causing the relationship to fail or not. example: in the DB I see 0x123456789 in my returned eloquent data I see 123456789
Person Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Person extends Model
{
protected $table = 'PERSON';
protected $primaryKey = 'ID';
public $incrementing = false;
public $timestamps = false;
public function info_all(){
return $this->belongsTo(Info_All::class, 'ID', 'ID');
}
}
Info Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Info_All extends Model
{
protected $table = 'INFO_ALL';
protected $primaryKey = 'ID';
public $incrementing = false;
public $timestamps = false;
public function person(){
return $this->hasOne(Person::class, 'ID', 'ID');
}
}
How I am testing the relationship:
php artisan tinker
$person = App\Person::first();
$person->info;
NULL
php artisan tinker
$info= App\Info::first();
$info->person;
NULL
I know this relationship exists in the DB and I can manuualy get them together with a query but the relationship feature of this framework would really be nice to get figured out.
Beign new to Laravel there are a few things I am unsure about, like if the third argument in the realationship is neccesary since I am declaring the $primaryKey. I declared the $primarykey in the first model because I assummed it is case sensative and my table has ID not id. That being said, I have been stuck on this for a couple days and feel like I have tested everything in every different combination.
Any help is appreciated.
Your relation is defined incorrectly. Try by adding following relation:
Person Model
public function info()
{
return $this->hasOne(Info_All::class, 'ID', 'ID');
}
Info_All model
public function person()
{
return $this->belongsTo(Person::class, 'ID', 'ID');
}
Then try it out in tinker:
$person = App\Person::first();
$person->info;
I am not sure but if eloquent removes the 0x from the start of the value then it can also cause the problem.
Try by removing 0x from your tables.

Custom Model and fields with Sentinel / Laravel

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'];
}

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 Many To Many Relationship getting data

this is my campus model
i have stripped the models for readability
and of course there is join table named as campus_user with id, campus_id, user_id
users can subscribe to campuses
now i want 2 things
1. Get all the users subscribed to a specific campus
2. Check to see if a specific user ( say with id = 1 ) is subscribed to a specific campus ( say with id = 2 )
class Campus extends \Eloquent{
protected $table = "campuses";
public function users(){
return $this->belongsToMany("User");
}
}
// this is my user model
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $table = 'users';
protected $hidden = array('password', 'remember_token');
public function campuses(){
return $this->belongsToMany('\Models\Campus');
}
}
Well the most "Eloquent like" way would be using relationship querying:
http://laravel.com/docs/4.2/eloquent#querying-relations
A simple example would be returning users with any campuses.
// Get users with any campus relationship.
$users = User::has('campuses')->get();
However you need something more powerful.
For 'users' in a specific 'campus'.
// Get 'users' in a 'campus' where the 'name' column equals 'foo'.
$campus = 'foo';
$users = User::whereHas('campuses', function($query) use ($campus) {
$query->where('name', $campus);
})->get();
For a specific 'user' in a specific 'campus' the code would almost be the same.
// Find the 'user' with a primary key of '1' in the 'campus' where
// the 'name' column equals 'foo'.
$primaryKey = 1;
$campus = 'foo';
$users = User::whereHas('campuses', function($query) use ($campus) {
$query->where('name', $campus);
})->find($primaryKey);
As you can see the last example replaced the get() method from the previous example.
You can do the same with the callback in the whereHas() method when you want to query using the primary key. This would result in the following.
...
$query->find($campus);
...
All the methods described above can be found in the Illuminate\Database\Eloquent\Builder class.
I would recommend taking a look at some of the source files to get a better understanding how request are handled.

Categories