Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

CLab's avatar
Level 3

Getting Call to member function null error even when the model and relationship are not null

Problem

I have a weird problem. I have a function in a trait defined as

  public function detachAndDeleteFile($hashName, $model)
  {
    //dd($hashName) outputs 'CeXJpRBr2CHblKEZPnPjyDqw9VWMjg-metac3BlZWR0ZXN0LVNMLTQzNi5wbmc=-.png'
    $file = DataFile::where('hashName', $hashName)->first();
	
	// dd($file) shows the file model and 
    // dd($file->steps()) gives an instance of `Illuminate\Database\Eloquent\Relations\MorphToMany`


    // if no other relations exist then delete the file
    $fileRelationsCount = $file->steps()->count() + $file->results()->count();
    
    if ($fileRelationsCount == 1) {
      $this->deleteFile($file);
    } 
    
    $model->files()->detach($file);

  }

The steps() method is defined in the DataFile model as

    public function steps(): MorphToMany
    {
        return $this->morphedByMany(Step::class, 'data_fileable');
    }

When the detachAndDeleteFile() method is called

Call to a member function steps() on null on the line $fileRelationsCount = $file->steps()->count() + $file->results()->count();

The dd($file) - shows the file (commented in the code above).

The dd($file->steps()) shows a MorphToMany relationship to the Step class (commented out in the code above).

Clearly the $hashName and the $file are found but still I get this error.

Tried

I already tried chatting with Larry but without any help. I also tried to eager load the steps and results relationships using

$file = DataFile::where('hashName', $hashName)->with(['steps','results'])->first();

but to no benefit.

Question

Please advise on how to troubleshoot/solve this further?

0 likes
8 replies
LaryAI's avatar
Level 58

The error "Call to a member function steps() on null" suggests that the $file variable is null when calling the steps() method. This means that the query DataFile::where('hashName', $hashName)->first() is not returning any results.

To troubleshoot this further, you can try the following steps:

  1. Check if the $hashName variable is correct and matches the value in the database.
  2. Verify that the DataFile model is correctly associated with the database table and has the hashName column.
  3. Check if there are any conditions or constraints in the DataFile model's query scope that might affect the query result.
  4. Ensure that the steps() relationship method in the DataFile model is correctly defined and returns the expected relationship.
  5. Verify that the Step model is correctly associated with the data_fileable pivot table.

If none of the above steps resolve the issue, you can try debugging the query by adding additional dd() statements:

$file = DataFile::where('hashName', $hashName)->first();
dd($file); // Check if the $file variable is null or contains the expected result

// If $file is not null, check the steps() relationship
dd($file->steps()); // Check if the steps() method returns the expected relationship

Additionally, you can try running the query manually in your database management tool to see if it returns any results.

If you're still unable to solve the issue, you can consider posting your question on the Laracasts forum or Laravel community forums, providing more details about your database structure and models.

CLab's avatar
Level 3

@LaryAI Unfortunately, I have already tried the suggestions and everything appears to be OK as I am still able to retrieve the $file->steps()->get() in dd() and view the steps related to the file.

Snapey's avatar

so $file is definitely null

dd($file) only proves that the first iteration of this function found a file. If the function is called more than once it could be the 2nd or 3rd instance that is null.

Find another way to try test or wrap if($file) around your queries

CLab's avatar
Level 3

@Snapey hi. So I only call this function once though, so I am not sure where the instance 2nd or 3rd comes in? Sorry I am not understanding.

tangtang's avatar

@CLab

something like this

public function detachAndDeleteFile($hashName, $model)
{
    $file = DataFile::where('hashName', $hashName)->first();
	
    if ($file) { // handle if $file is null
        $fileRelationsCount = $file->steps()->count() + $file->results()->count();
        
		// if ($fileRelationsCount == 1) isn't it determine this file still have other relation
		// base on this 'if no other relations exist then delete the file'
        if (!$fileRelationsCount) { // execute when the fileRelationsCount is 'false' or '0'
            $this->deleteFile($file);
        } 
        
        $model->files()->detach($file);
    } else {
        dd('Process terminated.');
    }
}
CLab's avatar
Level 3

Turns out because it was a trait the function name deleteFile was conflicting with a function where the trait was being used causing the confusion.

Snapey's avatar

@CLab so nothing to do with $file->steps() and all a waste of time.

CLab's avatar
Level 3

@Snapey I know šŸ¤¦ā€ā™‚ļø I feel so bad! But now I am thinking is it better to make this into a service rather than a trait - any advice when you should use which?

Please or to participate in this conversation.