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
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:
to
You are using different letter case. Class is defined as
Review
but you invokereview
:Unlike variable names, neither class names nor function names are case sensitive in PHP:
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 thatreview.php
andReview.php
are the same file, so it’ll work. In most Linux filesystems, it’s actually allowed to have two differentreview.php
andReview.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:So you don’t get the error right in the offending line, but later down the line when the class is eventually used.