skip to Main Content

In my Laravel app there are 3 Models:
Movie, User, Review

Review:

<?php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Review extends Model
{
    use HasFactory;

    protected $hidden = ['user_id','movie_id','created_at','updated_at'];

    public function movie(){
        return $this->belongsTo(Movie::class);
    }

    public function user(){
        return $this->belongsTo(User::class);
    }
}

Movie:

<?php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Movie extends Model
{
    use HasFactory;

    protected $hidden = ['created_at','updated_at'];

    public function review(){
        return $this->hasMany(review::class);
    }

    public function getAvg()
    {
        return $this->review()->average('rating');
    }

    public function count()
    {
        return $this->review()->count();
    }

    public function getBestRating()
    {
        return $this->review()->max('rating');
    }

    public function getWorstRating()
    {
        return $this->review()->min('rating');
    }
}

User:

<?php

namespace AppModels;

// use IlluminateContractsAuthMustVerifyEmail;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
use LaravelSanctumHasApiTokens;
use TymonJWTAuthContractsJWTSubject;

class User extends Authenticatable implements JWTSubject
{
    use HasApiTokens, HasFactory, Notifiable;

    public function review()
    {
        return $this->hasMany(Review::class);
    }
}

The query that doesn’t work

$movies = Movie::has('review')->with('review.user')->get();

In localhost it works fine. but after deploying in digitalOcean it returns "Class "AppModelsreview" not found"

I tried the console on digitalOcean:

> Movie::has('review')->get()
[!] Aliasing 'Movie' to 'AppModelsMovie' for this Tinker session.

 ERROR Class "AppModelsreview" not found in vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php on line 775.

but after running this in the same session:

Review::all()

the previous Movie::has(‘review’) works fine.

Why is that? Am I missing something?

2

Answers


  1. You are most likely loading the classes from case sensitive file system hence why this issue is causing the issue. Whilst PHP class names are not case sensitive. It is considered good practice to them functions as they appear in their declaration

    You need to change this line:

    return $this->hasMany(review::class);
    

    to

    return $this->hasMany(Review::class);
    
    Login or Signup to reply.
  2. You are using different letter case. Class is defined as Review but you invoke review:

    $this->hasMany(review::class);
    

    Unlike variable names, neither class names nor function names are case sensitive in PHP:

    class Example
    {
        public static function test(): void
        {
            echo 'Hello, World!';
        }
    }
    
    // This works
    eXaMpLe::TeSt();
    
    // This doesn't: Warning: Undefined variable $FOO
    $foo = 1;
    echo $FOO;
    

    Demo

    However, Laravel is using a PSR-4 compliant class auto-loader to locate and read the PHP files where classes are defined. Such auto-loader maps class names to file names, so whenever AppModelsReview is used in code, a filesystem path like /your/project/libraries/path/App/Models/Review.php is loaded. If any of your path components, either a directory or the file name, was created using a different case, whether it’ll work or not will depend on the case-sensitive flag in the file system. If your file system is something like NTFS (typical on Windows) it’ll decide that review.php and Review.php are the same file, so it’ll work. In most Linux filesystems, it’s actually allowed to have two different review.php and Review.php files, so they need to be considered different.

    It’s also worth nothing that the ::class syntax is just a string feature and doesn’t really trigger class autoloading:

    // This is fine
    echo DoesNotExist::class;
    

    So you don’t get the error right in the offending line, but later down the line when the class is eventually used.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search