laravels authentication system uses Id by default ,but lets say you have a bigger database with many tables how do you specify lets say the customer table
$user = User::where('name', '=', $name);
if($user->count()) {
$user=$user->first();
$user->status= 'super';
if($user->save()) {
return Redirect::route('home')
}
}
If your primary key is named differently than id you can configure the column name in the model:
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
protected $primaryKey = 'customer_id';
}
It's all in the documentation:
Note: Eloquent will also assume that each table has a primary key column named id. You may define a primaryKey property to override this convention. Likewise, you may define a connection property to override the name of the database connection that should be used when utilizing the model.
Related
I am want to update my records in my database using Eloquent model. I am having an error in updating user_profile table that saying where id is not null.
User Model
class User extends Model
{
public function profile()
{
return $this->hasOne('App\Models\Common\UserProfile');
}
}
UserProfile Model
class UserProfile extends Model
{
public function user()
{
return $this->belongsTo('\App\Models\User');
}
}
Controller
$user->fill($data);
$user->save();
$user->profile->fill($data);
$user->profile->save();
In MySQL query it looks like this:
UPDATE users, user_profiles
SET users.name='Test Name',
user_profiles.email='test#gmail.com'
WHERE users.id=1
AND user_profiles.user_id=1;
I know MySQL query but I'm new to Eloquent and I want to do it in Eloquent model. Maybe there are some in here that can provide an explanation on how the magic works in Eloquent.
By default eloquent assumes, that any model has an id column as primary key. If that is not the case, you need to "register" the primary key with
protected $primaryKey = 'user_id';
in the model class.
I have two models User and UserType declared as follows:
class User extends Model {
protected $table = 'user';
protected $primaryKey = 'user_id';
public function company() {
return $this->hasOne('App\Models\Company', 'company_id', 'company_id');
}
public function userType() {
return $this->hasOne('App\Models\UserType', 'user_type_id', 'user_type_id');
}
}
class UserType extends Model {
protected $table = 'user_type';
protected $primaryKey = 'user_type_id';
}
Now, I query the relationships using:
User::with('userType', 'company')->all()
Strangely, I get the company but userType is always null.
The MySQL query log shows that Laravel was able to get the user_type record.
The only difference between company and userType relationships are the data type of the primary keys. company.company_id is numeric while user_type.user_type_id is a string.
I think it is related to the data type of the keys however, I have a similar setup on Laravel 5.1 and it runs perfectly.
Laravel supports non-numeric primary keys but you need to set:
public $incrementing = false;
on your model class.
I corrected the issue by changing UserType definition to:
class UserType extends Model {
protected $table = 'user_type';
protected $primaryKey = 'user_type_id';
public $incrementing = false;
}
The first issue i notice with your relationship is that the first user_type_id you have passed to the hasOne function is wrong because you have the user_type_id as the primary key of the user_type table. The second argument of the hasone must be the foreign key of the parent table which is the user. So if you have anything like user_id in the user_type table use that instead.
But if thats not the case and user rather belongs to UserType then you have to change the hasOne to belongsTo.
So the belongsToMany relationship is a many-to-many relationship so a pivot table is required
Example we have a users table and a roles table and a user_roles pivot table.
The pivot table has two columns, user_id, foo_id... foo_id referring to the id in roles table.
So to do this we write the following in the user eloquent model:
return $this->belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');
Now this looks for an id field in users table and joins it with the user_id field in the user_roles table.
Issue is I want to specify a different field, other than id to join on in the users table. For example I have bar_id in the users table that I want to use as the local key to join with user_id
From laravel's documentation, it is not clear on how to do this. In other relationships like hasMany and belongsTo we can specify local key and foriegn key but not in here for some reason.
I want the local key on the users table to be bar_id instead of just id.
How can I do this?
Update:
as of Laravel 5.5 onwards it is possible with generic relation method, as mentioned by #cyberfly below:
public function categories()
{
return $this->belongsToMany(
Category::class,
'service_categories',
'service_id',
'category_id',
'uuid', // new in 5.5
'uuid' // new in 5.5
);
}
for reference, previous method:
I assume id is the primary key on your User model, so there is no way to do this with Eloquent methods, because belongsToMany uses $model->getKey() to get that key.
So you need to create custom relation extending belongsToMany that will do what you need.
A quick guess you could try: (not tested, but won't work with eager loading for sure)
// User model
protected function setPrimaryKey($key)
{
$this->primaryKey = $key;
}
public function roles()
{
$this->setPrimaryKey('desiredUserColumn');
$relation = $this->belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');
$this->setPrimaryKey('id');
return $relation;
}
On Laravel 5.5 and above,
public function categories()
{
return $this->belongsToMany(Category::class,'service_categories','service_id','category_id', 'uuid', 'uuid');
}
From the source code:
public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null,
$parentKey = null, $relatedKey = null, $relation = null)
{}
This is a recently added feature. I had to upgrade to 4.1 because I was also looking for this.
From the API documentation:
public BelongsToMany belongsToMany(string $related, string $table = null, string $foreignKey = null, string $otherKey = null, string $relation = null)
The $otherKey and $relation parameters were added in 4.1. Using the $foreignKey and $otherKey parameters allows you to specify the keys on both sides of the relation.
The best way is set the primary key.
class Table extends Eloquent {
protected $table = 'table_name';
protected $primaryKey = 'local_key';
belongsToMany allows to define the name of the fields that are going to store che keys in the pivot table but the method insert always the primary key values into these fields.
You have to:
define in the method belongsToMany the table and the columns;
then using protected $primaryKey = 'local_key'; you can choose which value store.
I recently went through the same problem where I needed to have an associated table that used ID's to link two tables together that were not Primary Keys. Basically what I did was create a copy of my model that models the pivot table and set the Primary Key to the value that I wanted it to use. I tried creating a model instance, settings the primary key and then passing that to the relation but Laravel was not respecting the primary key I had set ( using the ->setPrimaryKey() method above ).
Making a copy of the model and setting the primary key feels a little bit 'hackish' but in the end it works as it should and since Pivot table models are generally very small I don't see it causing any problems in the future.
Would love to see a third key option available in the next release of Laravel that lets you get more specific with your linking.
Suppose I have the following tables:
User:
-userID
-userName
...
Exercises:
-exerciseID
...
User model:
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
protected $primaryKey = 'userID';
...
public function hasPassedExercises() {
return $this->hasMany('Exercise', 'exerciseID');
}
}
I want to say that a User has many completedExercises, so when the user completes an exercise, I update the model like so:
Route::post('dbm/userPassedExercise', function () {
$user = User::with('hasPassedExercises')->find($_POST['userID']);
$exercise = Exercise::find($_POST['exerciseID']);
$user->hasPassedExercises->save($exercise);
});
However, this has no effect on any underlying table, as far as I have understood. I'm trying to make sense of the documentation and see how it applies to my problem. So my question is what is the right course of action to do here.
Should I create a table users_completed_exercises that has userID and exerciseID as foreign keys, and if so, how do I link them to my user when I do the update? Or is there a more elegant solution?
Indeed, you have to use a relationship table (called pivot table).
In the laravel documentation, you have to name your pivot table with your tables name ordered by their name (you have not to, but it's prefered).
We'll take your naming convention so : users_completed_exercises
So here we shoud have this :
users:
- userId // Unsigned Int PRIMARY KEY AUTO_INCREMENT
Exercises:
- exerciseId // Unsigned Int PRIMARY KEY AUTO_INCREMENT
users_completed_exercises:
- id // Unsigned Int PRIMARY KEY AUTO_INCREMENT
- exerciseId // Unsigned Int FOREIGN KEY REFERECES EXERCICES ON ID
- userId // Unsigned Int FOREIGN KEY REFERECES USERS ON ID
On the user model, you should have :
public function passedExercises()
{
// Alphabetical order of your id's are here, very important because laravel
// retreives the good ID with your table name.
return $this->belongsToMany('Exercise', 'users_completed_exercises', 'exerciseId', 'userId');
}
And the inverse on Excercise Model
public function usersWhoPassed()
{
// Alphabetical order of your id's are here, very important because laravel
// retreives the good ID with your table name.
return $this->belongsToMany('User', 'users_completed_exercises', 'exerciseId', 'userId');
}
Retreiving infos are now, so easy.
Route::post('dbm/userPassedExercise', function () {
// Don't use $_POST with laravel, they are exceptions indeed, but avoid as much as
// possible.
$user = User::find(Input::get('userId'));
$exercise = Exercise::find(Input::get('exerciseId'));
// Very important, use () on relationships only if you want to continue the query
// Without () you will get an Exercises Collection. Use ->get() or ->first() to end
// the query and get the result(s)
$exercise->usersWhoPassed()->save($user);
});
You can easly check if user has passed an exercise too
Route::get('/exercises/{id}/passed_users', function($id)
{
$exercise = Exercise::find($id);
if ($exercise->usersWhoPassed()
->where('userId', '=', Input::get('userId'))->count()) {
return 'User has passed';
}
return 'User has failed';
});
I have a User table and need to allow for users to have a parent user.
the table would have the fields:
id
parent_id
email
password
How would I define this self referencing relationship in Eloquent ORM?
I had some success like this, using your exact DB table.
User Model:
class User extends Eloquent {
protected $table = 'users';
public $timestamps = false;
public function parent()
{
return $this->belongsTo('User', 'parent_id');
}
public function children()
{
return $this->hasMany('User', 'parent_id');
}
}
and then I could use it in my code like this:
$user = User::find($id);
$parent = $user->parent()->first();
$children = $user->children()->get();
Give that a try and let me know how you get on!
I had a chain of self referencing contracts (a contract can be continued by another contract) and also needed self referencing. Each contract has zero or one previous and also zero or one next contract.
My data table looked like the following:
+------------------+
| contracts |
+------------------+
| id |
| next_contract_id |
+------------------+
To define the inverse of a relationship (previous contract) you have to inverse the related columns, that means setting
* foreign key column on the model table
* associated column on the parent table (which is the same table)
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Contract extends Model {
// The contract this contract followed
function previousContract()
{
// switching id and next_contract_id
return $this->belongsTo('App\Contract', 'id', 'next_contract_id');
}
// The contract that followed this contract
function nextContract()
{
return $this->belongsTo('App\Contract');
// this is the same as
// return $this->belongsTo('App\Contract', 'next_contract_id', 'id');
}
}
See http://laravel.com/docs/5.0/eloquent#one-to-one for further details.