Laravel Call to a member function first() on null - php

I'm using VueJS and Laravel for an application I'm developing. I've tried to search here for an answer, but I haven't found anything that works. Most of the times, it's because there's really nothing to return, but I've tried to debug my query quite a bit, and I don't understand why I keep getting a null.
So I'm trying to get information about the student who's logged in, so I'm doing an axios get on a route that executes the following:
public function getByUserId($id) {
//$student = $this->studentRepo->findByUserId($id);
$student = Student::where('user_id', $id)->first();
$inscription = Inscription::where('student_id', $student->id)->first();
$student->careers;
$res = $inscription ? new InscriptionResource($inscription) : '';
return response()->json([
'student' => new StudentResource($student),
'inscription' => $res,
]);
}
The thing is, it doesn't find the student with that user_id. I've checked if the user_id (param: $id) is getting there as expected and it is. I've also tried to get the query via ->toSql() and copy pasted the query on the database to test it and I do get the student I'm trying to search for. Thing is, it's not finding it in Laravel for some reason, I'm not sure why.
My student table does have the attribute "user_id", I've checked.
Student file:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Student extends Model {
use SoftDeletes;
protected $dates = ['deleted_at'];
public function charges() {
return $this->hasMany('App\Models\Payment');
}
}

Add the related column in the relation function
public function charges() {
return $this->hasMany('App\Models\Payment', '');
}

Related

How to check in a ::whereHas query for a certain column value? Laravel

My query has a model "Token" that belongsToMany "App". The model "App" also belongsToMany "Token". Both are connected through a model "AppToken" with a belongsTo "App/Token".
I have a working query that gets me all token that have an app connected. I check the token for active and i need to check if the app is active as well. I'm confused about the query for that. I tried many stuff already, as an example of what i want to achieve, i wrote a not working example code so it's more clear what i mean.
Current query:
$result = Token::whereHas('app')->where('active', 1)->get();
The results are all "active" token that have at least one "active or inactive" app connected.
But i need all "active" token that have at least one "active" app connected. (not working example):
$result = Token::whereHas('app')->where('tokens.active', 1)->where('apps.active', 1)->get();
My models:
Token.php
public function app()
{
return $this->belongsToMany(App::class, 'app_tokens');
}
App.php
public function tokenlist()
{
return $this->belongsToMany(Token::class, 'app_tokens', 'app_id', 'token_id');
}
AppToken.php
protected $fillable = [
'app_id', 'token_id',
];
/**
* Get the app record associated with the app_id.
*/
public function app()
{
return $this->belongsTo(App::class);
}
/**
* Get the token record associated with the token_id.
*/
public function tokenlist()
{
return $this->belongsTo(Token::class);
}
instead of whereHas() you can try with with() method. It will work for me.
The example is written below.
App/Token.php
public function app(){
return $this->hasMany('App\App’)->where(‘active’,1);
}
App/App.php
public function token(){
return $this->hasMany('App\Token’);
}
Query:-
1)If the cap is your column name in the tokens table then you can use orderBy() like this.
$result = Token::with(‘app')->where('active',1)->orderBy(‘cap')->get();
Or
2)If not then use only get().
$result = Token::with(‘app')->where('active',1)->get();
I think i found the answer to my question :)
$result = Token::whereHas('app',function ($q){
$q->where('active', 1);
})->where('active', 1)->get();

Copying Data from table to another table and applying one to many relationship

This is my Report Model
protected $fillable = [
'site_url',
'reciepients',
'monthly_email_date'
];
public function site()
{
return $this->belongsTo('App\Site');
}
This is my Site Model
public function report()
{
return $this->hasMany('App\Report');
}
This is my ReportController
public function showSpecificSite($site_name)
{
$records = DB::table('reports')
->select('email_date','url','recipient')
->whereHas('sites', function($query){
$query->where('site_name',$site_name);
})
->get();
return view('newsite')->with('records',$records)
->with('site_name',$site_name);
}
My Controller is not yet working as well.
The thing is I would like to copy all the three files from sites table to reports table.
Is it possible in insertInto ?
My code on ReportController shows you that I'm selecting data from reports table but I am the one who puts data to reports table to see the output but it is not yet working because of the it cant reach out the value of site_name even though I already put a relationship between the two tables.
You're not actually using Eloquent in your controller you're just using the Query Builder (DB). This will mean that you don't have access to anything from your Eloquent models.
Try:
$records = \App\Report::whereHas('site', function($query) use($site_name) {
$query->where('site_name', $site_name);
})->get(['id', 'email_date', 'url', 'recipient']);
I've added id to the list of columns as I'm pretty sure you'll need that to use whereHas.
NB to use a variable from the parent scope inside a closure you need to pass it in using use().

Failure to extract data from a relationship with laravel

I am trying to make a one-to-many relationship, but I get the following error
Undefined property: stdClass::$client (View:
C:\wamp\www\intranet\resources\views\users\list.blade.php)
The problem is that I am working with an existing database that in the tables does not have id fields, and the foreign keys would also be the typical ones like client_id
My model Client.php
class Client extends Model
{
protected $connection = 'dpnmwin';
protected $table = 'nmundfunc';
public function employee(){
return $this->hasMany('App\Employee');
}
}
My model Employee.php
class Employee extends Model
{
protected $connection = 'dpnmwin';
protected $table = 'nmtrabajador';
public function client(){
return $this->belongsTo('App\Client', 'COD_UND');
}
}
In nmtrabajador COD_UND field would be the foreign key that relates to nmundfunc.
And I try to get the data out like this: {{$user->client->CEN_DESCRI}}.
but it does not throw me the error, how can I solve it?
My Controller where I send in sight
public function index(){
$users = DB::connection('dpnmwin')->table('nmtrabajador')->where('CONDICION', '=', 'A')->get();
return view('users.list',array(
'users' => $users
));
}
You have to call basis on relations.
This code will return you data.
If you have id then you can find by id like below
$employee=Employee::find(1);
Or if you want to fetch all data then you can call all method.
Employee::all();
And then you can just get it by relation as you define in models.
$client=$employee->client->CEN_DESCRI;
Retrieving data from the instance is based on the methods which we have use.
Here in this answer, you can get that
Property [title] does not exist on this collection instance
I hope it will work.
If table doesn't have 'id' as primary key you should specify what the primary key is inside your model:
protected $primaryKey = 'your_primary_key';
Relation looks good, after that you must make sure $user is a defined instance of Employee, because your error probably means that your instance wasn't even defined, so for example if you are using list.blade.php, you need to change the return of your controller and indicate that you want to pass data to your view, for example you could do it like this:
return view('users.list', compact('user'));
Where user is an instance of Employee saved on '$user'
Update
First you should check your user is retrieved properly, you can check it by placing a dd($user)
And when you return a view you can pass information to it, a cleaner way of doing what you are trying to do is what I wrote earlier so you would end up having something like this:
public function index()
{
$users = DB::table('nmtrabajador')
->where('CONDICION', '=', 'A')
->get();
// dd($user) for debugging you are retrieving the user properly
return view('users.list', compact($users));
}

use relationship in model accessor in laravel

Suppose I have a Course model like this :
class Course extends Model
{
public $primaryKey = 'course_id';
protected $appends = ['teacher_name'];
public function getTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
}
public function teacher ()
{
return $this->belongsTo('App\User', 'teacher', 'user_id');
}
}
And in the other hand there is a User model like this :
class User extends Authenticatable
{
public $primaryKey = 'user_id';
protected $appends = ['full_name'];
public function getFullNameAttribute ()
{
return $this->name . ' ' . $this->family;
}
public function course ()
{
return $this->hasMany('App\Course', 'teacher', 'user_id');
}
}
As you can see there is a hasMany relationship between those.
There is an full_name accessor in User model.
Now I want to add a teacher_name accessor to Course model that uses it's teacher relations and gets full_name of teacher and appends to Course always.
In fact I want whenever call a Course model, it's related teacher name included like other properties.
But every time , when call a Course model , I got this error :
exception 'ErrorException' with message 'Trying to get property of non-object' in D:\wamp\www\lms-api\app\Course.php:166
That refers to this line of Course model :
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
I do not know how can I solve that and what is problem exactly.
Yikes some interesting answers here.
FYI to those coming after me- getFooAttribute() should return the data, and not modify the internal attributes array.
If you set a new value in the attributes array (that doesnt exist in this model's db schema) and then attempt to save the model, you'll hit a query exception.
It's worth reading up the laravel docs on attribute accessors/mutators for more info.
Furthermore, if you need to access a related object from within the model (like in an accessor) you ought to call $related = $this->getRelation('foo'); - note that if the relation isnt loaded (e.g., if you didnt fetch this object/collection with eager loaded relations) then $this->getRelation() could return null, but crucially if it is loaded, it won't run the same query(ies) to fetch the data again. So couple that with if (!$this->relationLoaded('foo')) { $this->loadRelation('foo'); }. You can then interact with the related object/collection as normal.
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
Should be
$this->attributes['teacher_name'] = $this->teacher->full_name;
First thing is that you want to reference the relationship, so loose the brackets (), and because the relationship is belongsTo, you will have one user / teacher returned. So you don't need the first().
We haven't seen your fields but probably you will have to change:
return $this->belongsTo('App\User', 'teacher', 'user_id');
to
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
where foreign_key and other_key are the primary keys that you need to make the join on.
Check this link from the documentation for reference:
https://laravel.com/docs/5.4/eloquent-relationships#one-to-many-inverse
the right way to do this is:
COURSE
public function setTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher->full_name;
}
100% working for me.
I have one to one relationship between Order and Shipment. I have to add the accessor of shipments table column from orders table.
function getOrderNoAttribute()
{
$appendText = "OR100";
if($this->orderShipment()->first()) {
$appendText = $this->orderShipment()->first()->is_shipping === 1 ? "ORE100" : "OR100";
}
return $appendText . $this->attributes['id'];
}
This error is only object data to array use or array data to object data use.
example::
$var->feild insted of $var[feild]
$var[feild] insted of $var->feild
You should use return for accessors . something like this :
public function getTeacherNameAttribute ()
{
return $this->teacher()->first()->full_name ?? '';
}
maybe a course hasn't teacher.

Laravel Eloquent::Find() returning NULL with an existing ID

It's pretty straightforward as it's the most basic thing but I don't know what I'm missing:
Having a model called Site
I'm using Eloquent ORM, so when I call (in a controller)
$oSite = Site::find(1)
and then
var_dump($oSite);
It returns a value of NULL.
But when I check the database, the table 'sites' actually contains the following item:
id: 1
user_id: 1
name: test
In my Site model I have the following code:
use Illuminate\Database\Eloquent\ModelNotFoundException;
Class Site extends Eloquent {
protected $table = 'sites';
protected $fillable = ['user_id', 'name'];
}
Instead, if I gather the item with the following:
$oSite = DB::table('sites')
->where('id', 1)
->first();
It works and I get the correct register.
What I'm doing wrong? Which part of the documentation I didn't get?
EDIT:
Model code can be checked above.
Controller:
use Illuminate\Support\Facades\Redirect;
class SiteManagementController extends BaseController {
...
public function deleteSite()
{
if (Request::ajax())
{
$iSiteToDelete = Input::get('siteId');
$oSite = Site::find($iSiteToDelete);
return var_dump($oSite);
}
else
{
return false;
}
}
}
EDIT 2: (SOLVED)
Real reason why wasn't working:
I had originally in my model code the following:
use Illuminate\Database\Eloquent\SoftDeletingTrait;
use Illuminate\Database\Eloquent\ModelNotFoundException;
Class Site extends Eloquent {
protected $table = 'sites';
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
protected $fillable = ['user_id', 'name'];
}
Problem was I added a 'deleted_at' column after I started the project and when I applied migrations, I didn't have softdeleting enabled.
Obviously, I did a second error, forgetting to enable 'deleted_at' to be nullable, hence all inserts went had a wrong timestamp (0000-00-00 ...).
Fix:
Made nullable 'deleted_at' column.
Set all wrong 'deleted_at' timestamps to NULL.
Check you are getting Input::get('siteId') correctly. if you are getting it then try to convert it into integer i.e
$iSiteToDelete = intval(Input::get('siteId'));
You're not returning your model.
var_dump prints output and returns nothing.
do this instead:
dd($oSite); // stands for var_dump and die - a helper method
and even better, simply return the model:
return $oSite; // will be cast to JSON string
In my case I was using a custom query with the DB facade. I neglected to skip records that have a deleted_at in my DB query. When showing all the records, it worked with IDs that had already been deleted, so methods like find that if they were considering the deleted_at, did not find the record.
Layer eight.
For the future if you encounter a similar problem you can check what SQL queries laravel is sending to the database.
Todo so just enable query logging by using DB facade:
\DB::enableQueryLog();
Before sending request to database.
Then after using find() or get() you can get all requests by:
\DB::getQueryLog();
You can getQueryLog into dd() function and see what database queries were made.

Categories