Laravel Eloquent one --> many relationship assigning parent - laravel

User model has many friends primary key id
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function friends()
{
return $this->hasMany(Friend::class);
}
}
Friend model; belongs to user. Foreign key user_id.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Friend extends Model
{
protected $guarded = ['id'];
//Make sure birthday is always in right format
public function setBirthdayAttribute($value)
{
//Put in mysql format
$this->attributes['birthday'] = date("Y-m-d",strtotime($value));
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Error when updating user with following controller code:
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Friend $friend
* #return \Illuminate\Http\Response
*/
public function update(Request $request, Friend $friend)
{
$friend->fill($request->all());
//Assign user to logged in user...does NOT work; things it is a column
$friend->user = \Auth::user();
$friend->save();
return redirect(action('FriendsController#index'));
}
Error message when saving:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'user' in 'field list' (SQL: update `friends` set `last_name` = Muench!!, `updated_at` = 2018-09-28 13:26:01, `user` = {"id":1,"name":"Chris","email":"me#chrismuench.com","email_verified_at":null,"created_at":"2018-09-27 19:52:03","updated_at":"2018-09-27 19:52:03","braintree_id":null,"paypal_email":null,"card_brand":null,"card_last_four":null,"trial_ends_at":null} where `id` = 8)
Is there a reason I cannot assign user with a user object? I know I could set the user_id column but this would be nice if I could pass around objects.

If you want to assign object and not property in your controller you need to add the following mutator
public function setUserAttribute($user)
{
$this->attributes['user_id'] = $user->id;
}
to your Friend object.
However it could be quite risky, because relationship name is also user, so it's better to use other name (for example friend_user and then method name setFriendUserAttribute) or to use Eloquent associate method instead:
$friend->user()->associate(\Auth::user());

Related

Laravel relationship with additional where statement

I know I can define a relationship by
Class Users extends Model{
function profile(){
return $this->hasOne(Profile::Class);
}
}
is there a way like adding extra query to the relationship like other than foreign key and local key that is available to define, I want to only get those records of Profile model that field active contains a value of 1. Profile model has a field named active. Any help, ideas is greatly appreciated, thank you in advance.
you can simply try
return $this->hasOne(Profile::Class)->where('active', 1);
but better approach will be using Scope like this.
create a folder app/Scopes and add a new file ActiveUserOnly.php
place this code there
namespace App\Scopes;
use \Illuminate\Database\Eloquent\Builder;
use \Illuminate\Database\Eloquent\Scope;
use \Illuminate\Database\Eloquent\Model;
class ActiveUsersOnly implements Scope {
/**
* #inheritdoc
*
* #param Builder $builder
* #param Model $model
*
* #return Builder|void
*/
public function apply( Builder $builder, Model $model ) {
return $builder->where( 'active', '=', true );
}
}
add this code to the top of Profile model.
use App\Scopes\ActiveProfilesOnly;
add this code in your Profile model.
protected static function boot() {
parent::boot();
static::addGlobalScope( new ActiveProfilesOnly() );
}
then this code will work in your User model.
Class Users extends Model{
function profile(){
return $this->hasOne(Profile::Class);
}
}

Get data from different tables using inner joins

I have column in results as 'user_id','test','subject' and in datatable i want to get the 'test_name' which is saved in 'tests' table, Student name 'name' saved in 'users' and 'subject name' in table 'subjects' in column 'subjects' now tell me what is the best way to get this data.
So far i had tried this but getting null while dumping.
$result = DB::table('results')
->where([
['results.subject',$request->subject],
['test',$request->test],
['user_id',$request->name]
])
->join('users','results.user_id','=','users.name')
->join('tests','tests.id','=','results.test')
->join('subjects','subjects.id','=','results.subject')
->select('results.*','users.name','tests.test_name','subjects.subjects As s_subject')
->first();
dd($result);
anyone who can guide me the best possible solution.
You should use the power of the Eloquent model of Laravel. You have to create Results model class as follow(and obviously need to create User, Test and Subject model class)
Results.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Carbon\Carbon;
class Results extends Model
{
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
/**
* Get the user profile associated with the results.
*/
public function user()
{
return $this->hasOne('App\User', 'user_id');
}
/**
* Get the test details associated with the results.
*/
public function test()
{
return $this->hasOne('App\Test', 'test');
}
/**
* Get the subject associated with the results.
*/
public function subject()
{
return $this->hasOne('App\Subject', 'subject');
}
}
Controller.php
$results = App\Results::where(['subject' => $request->subject, 'test' => $request->test, 'user_id' => $request->name])->first();
Now you will get the Result object with the test, subject, and test property.
Note that:- You should provide the output when you are asking any question.

Laravel Eloquent How Can I Select Using Condition "where" for pivot table

I have three database tables called user(id,name), group(id,name) and user_group(user_id, group_id,valid_before) with relations many to many.
class User extends Model
{
protected $table = 'user';
public function groups()
{
return $this->belongsToMany(Group::class, 'user_group')
->withPivot('valid_before');
}
}
class Group extends Model
{
protected $table = 'group';
public $timestamps = false;
public function user()
{
return $this->belongsToMany(User::class, 'user_group');
}
}
How can I select all users (using Eloquent) who have
valid_before < $some_date
?
There are many ways to achieve this goal. I'll show you an example using query scopes.
In your User class you have to make a little update:
class User extends Model
{
protected $table = 'user';
public function groups()
{
return $this->belongsToMany(Group::class, 'user_group')
//->withPivot('valid_before'); <-- Remove this
}
}
and create a scope in your Group model:
class Group extends Model
{
protected $table = 'group';
public $timestamps = false;
public function user()
{
return $this->belongsToMany(User::class, 'user_group');
}
/**
* This scope gets as input the date you want to query and returns the users collection
*
* #param \Illuminate\Database\Eloquent\Builder $query
* #param string $date
* #return \Illuminate\Database\Eloquent\Builder
*/
public function scopeUsersValidBefore($query, $date)
{
return $query->users()->wherePivot('valid_before', '<', $date);
}
}
Now, I imagine you have a GroupController that somewhere creates a query to retrieve the valid before users. Something like:
// [...]
$users = Group::usersValidBefore($yourDate)->get();
// [...]
If you want to create the query from the other side, I mean you want to use the User model and list all the Users that has a pivot relation with valid_before populated, than the right approach is creating a UserGroup intermediate model that can be easily used to create a query.
If you are using Laravel 8.x.x
It's much easier with Inline Relationship Existence Queries
If you would like to query for a relationship's existence with a single, simple where condition attached to the relationship query, you may find it more convenient to use the whereRelation and whereMorphRelation methods. For example, we may query for all posts that have unapproved comments:
use App\Models\Post;
$posts = Post::whereRelation('comments', 'is_approved', false)->get();
Of course, like calls to the query builder's where method, you may also specify an operator:
$posts = Post::whereRelation(
'comments', 'created_at', '>=', now()->subHour()
)->get();

laravel4 How can i use eloquent in my controller?

I would like to create a relationship between 2 tables with eloquent but i can't find exactly how to proceed...
Here are my 2 models with relationship :
Table "etablissement":
<?php class Etablissement extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'etablissement';
public function annulation()
{
return $this->hasMany('Annulation');
}}
Table "annulation":
<?php class Annulation extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'annulation_remboursement';
public function etablissement ()
{
return $this->belongsTo('Etablissement');
}}
In the "Etablissement" table there is an id for each etablissement (id_etablissement) and in the "annulation" there is a column with the id_etablissement. How can i return in my controller a relation in order to have the etablissement's name with the annulation->id_etablissement :
class AnnulationsController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
}
It should be something like this within your index method:
$annulation = Annulation::find(1);
$annulation->etablissement->name
The annulation_remboursement table should have a establissement_id field.
Perhaps the error may be in the keys of the relation.
In https://laravel.com/docs/4.2/eloquent#one-to-one we see:
Take note that Eloquent assumes the foreign key of the relationship based on the model name. In this case, Phone model is assumed to use a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method. Furthermore, you may pass a third argument to the method to specify which local column that should be used for the association:
return $this->hasOne('Phone', 'foreign_key');
return $this->hasOne('Phone', 'foreign_key', 'local_key');
[...] One To Many: Again, you may override the conventional foreign key by passing a second argument to the hasMany method. And, like the hasOne relation, the local column may also be specified:
return $this->hasMany('Comment', 'foreign_key');
return $this->hasMany('Comment', 'foreign_key', 'local_key');
* You should also checkout Defining The Inverse Of A Relation at the same page.
So, in your case you have a key named id_etablissement but Laravel is searching for etablissement_id. If you wish to override this behaviour and specify a key you should do something like:
protected $table = 'etablissement';
public function annulation()
{
return $this->hasMany('Annulation','id_etablissement');
}
and according to "The Inverse Of A Relation"
protected $table = 'annulation_remboursement';
public function etablissement ()
{
return $this->belongsTo('Etablissement','id_etablissement');
}
Note that I didn't put any of the local keys, but those will be the third parameter of the relation.

Using Laravel is it possible to bypass the need for remember_token using an external user database

With a recent update of Laravel they require a remember_token, and also updated_at.
When logging in and out I get:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'remember_token' in 'field list' (SQL: update `account` set `remember_token` = s8XPDCdNdJnjbLj7MlDRO1Cy5owwjxdfW1rYVhd6QpePIltqPkavr9l3KUbd, `updated_at` = 2014-07-30 14:09:37 where `id` = 5)
I am using an external user database which I don't want to create these extra fields on, as it is used also on a game server which I don't want to mess with..
Is there a way to bypass the need for both of these columns?
I'm pretty sure using Laravel's built in Auth system (Guard) makes you use UserInterface which, in turn, makes you define these. However, you could just fake it by having these methods but making them return useless information.
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface
{
use UserTrait, RemindableTrait;
protected $hidden = array('password', 'remember_token');
public $timestamps = false;
public function getRememberToken()
{
return '';
}
public function setRememberToken($value)
{
}
public function getRememberTokenName()
{
// just anything that's not actually on the model
return 'trash_attribute';
}
/**
* Fake attribute setter so that Guard doesn't complain about
* a property not existing that it tries to set.
*
* Does nothing, obviously.
*/
public function setTrashAttributeAttribute($value)
{
}
}
That might just do what you want - basically override these functions to not work correctly, which means that 1) you don't need to mess with your DB and 2) when the functionality doesn't work it's okay because you're not using it anyway.
And as #neeraj says, for the created_at thing, just do $timestamps = false and hope for the best. Updated model above to reflect this.
Yes it is possible. This code should allow you to avoid having to use the 'remember_token' in your users table
public function getRememberToken()
{
return null; // will not support
}
/**
* Set the token value for the "remember me" session.
*
* #param string $value
* #return void
*/
public function setRememberToken($value)
{
// will not support
}
/**
* Get the column name for the "remember me" token.
*
* #return string
*/
public function getRememberTokenName()
{
return null; // will not support
}
public function setAttribute($key, $value)
{
$isRememberTokenAttribute = $key == $this->getRememberTokenName();
if( ! $isRememberTokenAttribute )
{
parent::setAttribute($key, $value);
}
}
Try removing below interface from your modal
RemindableInterface
For created_at and updated_at, you can write the below line in modal:
public $timestamps = false;
For example, if your modal name is Admin then code should look like
class Admin extends Eloquent implements UserInterface
{
public $timestamps = false;
}

Resources