Call to a member function update() on null - php

I'm building my first Laravel app. That's my first problem that I can't overcome.
I tried to google something about it, but I couldn't find something that could help me.
class ProfilesController extends Controller
{
public function index(User $user)
{
return view('profiles.index', compact('user'));
}
public function edit(User $user){
return view('profiles.edit', compact('user'));
}
public function update(User $user){
$data = request()->validate([
'description' => 'required',
]);
$user->profile->update($data);
return redirect("{$user->id}/edit");
}
}
I want to get through that and update $data.
Edit
public function profile() {
return $this->hasOne(Profile::class);
}
public function posts(){
return $this->hasMany(Post::class)->orderBy('created_at', 'DESC');
}

Try this:
optional($user->profile)->update($data);
You can see the official documentation of optional() helper here.

I think you cannot update directly on an instance, you'd have to do : User::where('user_id', $user->id);
If you want to "update" an instance, you would have to do : $user->description = $data['description']; $user->save();

Do this:
if($user->profile) {
$user->profile()->update($data);
}
Hope this will help you.

I would imagine this is because the user doesn't have a profile by default.
One way you can get around this is by using withDefault() on your profile relationship in your User model e.g.
public function profile()
{
return $this->hasOne(Profile::class)->withDefault();
}
You would then need to change your controller code slightly since the profile might not exist:
Change:
$user->profile->update($data);
To:
$user->profile->fill($data)->save();

I had the same issue. As it turned out I forgot to create a new empty profile while creating a new user. So i was calling an update on the user's profile in this case null.
Try adding this to the User model and later migrate:fresh your data.
protected static function boot()
{
parent::boot();
static::created(function ($user) {
$user->profile()->create();
});
}
This will create a new profile for user automatically.

Related

Laravel get user data with profile

I have user and profile models with followers/following. What I want is to get the User data with the Profile data merged when calling Profile::followers. Now I only retrieve the profile data.
So I added the user() to Profile.php so I can call Profile::followers->user()... but no result. Can someone explain how to merge the User with Profile when calling the following() function?
User.php model
public function following()
{
return $this->belongsToMany(Profile::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
Profile.php model
public function followers()
{
return $this->belongsToMany(User::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
I don't know if I came late but the correct way to get a user profile would be
$profile = Auth::user()->profile;
I don't know if this would help, using Auth::user() you get to fetch the current user and since you have a relationship with the profile you can call the profile() public function without the braces.
I hope this helps anyone.

Laravel Undefined Method

I am getting the following error on my query when the interest method exists in my model.
Call to undefined method Illuminate\Database\Query\Builder::interest()
Controller:
public function index() {
$user_id = auth()->user()->id;
$user = User::find($user_id);
$interests = Space::where('user_id', $user_id)->interest()->get();
return view('dashboard')->with('space', $user->space)->with('interest', $interests->space);
}
Space Model:
public function user(){
return $this->belongsTo(User::class);
}
public function interest(){
return $this->hasMany(Interest::class);
}
Interest Model:
public function user(){
return $this->belongsTo(User::class);
}
public function interest(){
return $this->belongsTo(Space::class);
}
Space::where('user_id', $user_id)->interest()->get();
The Line Shows Error Because the method interest is not existed in query builder or Model Scopes
But I think You have Misundestood something
Loading Relation In collection
Space::where('user_id', $user_id)->with('interest')->get();
Will Work
And
$singleFind = Space::findOrFail($yourId)->interest();
Will Work as you expected
Hope its clear
Try with this,
First of all you can access authenticated user id by this auth()->id()
For relationship in controller
$interests = Space::with(['interest'])->where('user_id', $user_id)->get();
For more
Laravel eager loading
Hope this helps:)

how to fix relationship error between models?

I have set up two models and made the relationship between them. I want to pass the attributes of the user as well as the user_detail.
I have used a similar code somewhere and it worked perfectly. But it is not working here.
//This is the function in "User.php" model.
public function user_detail(){
return $this->hasOne('App\Profile');
}
//This is the function in "Profile.php" model.
public function user(){
return $this->belongsTo('App\User');
}
//edit function in ProfileController
public function edit($id)
{
$user=User::find($id);
return view('profile.edit')->with('data',$user->user_detail);
}
When I click the edit button in the view, I expect the extract all the details from user table as well as from user_detail table.
I think you should edit your this code a little bit
public function edit($id)
{
$user=User::findOrFail($id);
return view('profile.edit')->with('data',$user);
}
And in your blade file (profile.edit), You can get all details from User and Profile Model.
{{ $data->id }}
{{ $data->user_detail->YOURPARAMETERS }}
The problem is with the relationship naming. Make it camelCase like,
//This is the function in "User.php" model.
public function userDetail(){
return $this->hasOne('App\Profile');
}
//edit function in ProfileController
public function edit($id)
{
$user=User::find($id);
return view('profile.edit')->with('data',$user->userDetail);
}
Reference: https://github.com/laravel/framework/issues/4307#issuecomment-42037712
try using where instead of find and then use with:
$user = User::where('id', $id)->with('user_detail')->first();
return view('profile.edit')->with('data', $user);
In your model:
public function user_detail(){
return $this->hasOne('App\Profile', 'student_no');
}

Laravel 5.1: Call to undefined method Illuminate\Database\Query\Builder::fill()

I am trying to get this line to work $user->profile()->fill($input['profile'])->save();
Following much discussion and failed attempts
I need help filling an eloquent model
Also had a probelm with guarding
http://laravel.io/forum/01-06-2016-massassignmentexception-ignoring-fillable-guarded-is-set
Which i overcame with protected $guarded = ['id'];
Profile model
public function user(){
return $this->belongsTo('App\User');
}
User Model
public function profile(){
return $this->hasOne('App\Profile', 'user_id');
}
Controller
public function update(Request $request, $id)
{
$user = User::with('profile')->findOrFail($id);
$input = $request->all();
if(is_null($user->profile)){
$profile = new Profile($input['profile']);
$user->profile()->save($profile);
alert()->warning('New profile creation attempt!');
}else{
// $user->profile()->fill($input['profile'])->save();
$user->profile->title = $input['profile']['title'];
$user->profile->facebook_username = $input['profile']['facebook_username'];
$user->profile->meetup_user_id = $input['profile']['meetup_user_id'];
$user->profile->save();
// dump($input['profile']['title']);
// dump($user->profile->title);
//Unless it fails silently like before.
alert()->success('Profile Saved!');
}
return redirect()->route('admin.users.edit', [$id]);
}
Notice how I am manually filling, this is not ideal obviously. this is the result i am trying to achieve
as per my understanding, you want to fill profile Attributes in a single line,
did you try fill() method ??
try this way in your else section or whereever your want it, I hope that might help you
$profile = new Profile;
$profile->fill($input['profile']);
$user->profile()->save($profile);

Laravel models to return null relation?

I am writing a website for photo posts and I have these functions relating likes (they determine if the user is liking the specific post or not)
Post Model:
public function likes()
{
return $this->hasMany('Like');
}
public function isLiked()
{
return $this->likes()->where('user_id', Auth::user()->id);
}
Post Controller function for example:
public function postsByType($type)
{
if($this->user){
$posts = Post::with('isLiked')->where('type', '=', $type)->paginate(12);
} else {
$posts = Post::where('type', '=', $type)->paginate(12);
}
return $posts;
}
Is there any way to return null in MODEL function when user is not logged in, without running a query?
I want to avoid writing that if in post controller
I thought about the following solution but it's not working...
public function isFollowing()
{
return $this->setRelation('isFollowing', null);
}
getting this error:
Call to undefined method Illuminate\Database\Query \Builder::addEagerConstraints()
Since you probably always want to fetch the relation (except if there's no user logged in) I suggest you do something like this in your model:
(I also renamed the relationship to liked, you'll see later why)
public function newQuery(){
$query = parent::newQuery();
if(Auth::check()){
$query->with('liked');
}
return $query;
}
Now every time a query is run with the model with('isLiked') will be added if the user is logged in.
One problem remains though. If you access isLiked the query will be run anyways. And even for every post because it's not eager loaded. You can fix that by adding an attribute accessor:
public function getIsLikedAttribute(){
if(Auth::guest) return false;
return ! $this->liked->isEmpty();
}
So in your view you can just do this:
#if($post->isLiked)
Note: It would be nicer to move the things inside newQuery() to a global scope. Make sure to check out how to do that in the documentation if you're interested.
Here's an example with a scope. Create a class, let's call it LikedScope:
class LikedScope implements Illuminate\Database\Eloquent\ScopeInterface {
public function apply(Builder $builder, Model $model){
if(Auth::check()){
$builder->with('liked');
}
}
public function remove(Builder $builder, Model $model){
}
}
And then add it to your model:
public static function boot(){
parent::boot();
static::addGlobalScope(new LikedScope);
}

Categories