Stage 2

Model Creation with Relationships

Create all the necessary models with proper Eloquent relationships.

Task

In this stage, you'll create all the necessary models with proper Eloquent relationships. This will allow you to easily query related data in your application.

Required Relationships

  • User: hasMany orders, reviews, wishlists
  • Product: belongsTo category, hasMany reviews, orderItems, belongsToMany users (through wishlists)
  • Category: hasMany products, belongsTo parent, hasMany children
  • Order: belongsTo user, hasMany orderItems
  • OrderItem: belongsTo order, product
  • Review: belongsTo user, product
  • Wishlist: belongsTo user, product

Implementation Steps

1. Create the models

php artisan make:model Product
php artisan make:model Category
php artisan make:model Order
php artisan make:model OrderItem
php artisan make:model Review
php artisan make:model Wishlist

2. Implement the User model

Update the User model with the required relationships:

app/Models/User.php
php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\Relations\HasMany;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
'address',
'phone',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
// TODO: Implement the orders relationship
// This should return a hasMany relationship to the Order model
public function orders(): HasMany
{
// Your code here...
return $this->hasMany(Order::class);
}
// TODO: Implement the reviews relationship
// This should return a hasMany relationship to the Review model
public function reviews(): HasMany
{
// Your code here...
return $this->hasMany(Review::class);
}
// TODO: Implement the wishlists relationship
// This should return a hasMany relationship to the Wishlist model
public function wishlists(): HasMany
{
// Your code here...
return $this->hasMany(Wishlist::class);
}
}

3. Implement the Product model

app/Models/Product.php
php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name',
'description',
'price',
'stock_quantity',
'category_id',
];
// TODO: Implement the category relationship
// This should return a belongsTo relationship to the Category model
public function category(): BelongsTo
{
// Your code here...
return $this->belongsTo(Category::class);
}
// TODO: Implement the reviews relationship
// This should return a hasMany relationship to the Review model
public function reviews(): HasMany
{
// Your code here...
return $this->hasMany(Review::class);
}
// TODO: Implement the orderItems relationship
// This should return a hasMany relationship to the OrderItem model
public function orderItems(): HasMany
{
// Your code here...
return $this->hasMany(OrderItem::class);
}
// TODO: Implement the users relationship (through wishlists)
// This should return a belongsToMany relationship to the User model through the wishlists table
public function users(): BelongsToMany
{
// Your code here...
return $this->belongsToMany(User::class, 'wishlists');
}
}

4. Implement the Category model

app/Models/Category.php
php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Category extends Model
{
use HasFactory;
protected $fillable = [
'name',
'description',
'parent_id',
];
// TODO: Implement the products relationship
// This should return a hasMany relationship to the Product model
public function products(): HasMany
{
// Your code here...
return $this->hasMany(Product::class);
}
// TODO: Implement the parent relationship
// This should return a belongsTo relationship to the Category model (self-referencing)
public function parent(): BelongsTo
{
// Your code here...
return $this->belongsTo(Category::class, 'parent_id');
}
// TODO: Implement the children relationship
// This should return a hasMany relationship to the Category model (self-referencing)
public function children(): HasMany
{
// Your code here...
return $this->hasMany(Category::class, 'parent_id');
}
}

5. Implement the remaining models

Now implement the Order, OrderItem, Review, and Wishlist models with their relationships.

Hint:

For belongsTo relationships, use:
return $this->belongsTo(ModelName::class);

For hasMany relationships, use:
return $this->hasMany(ModelName::class);

For belongsToMany relationships, use:
return $this->belongsToMany(ModelName::class, 'pivot_table');

For self-referencing relationships, specify the foreign key:
return $this->belongsTo(Category::class, 'parent_id');

Checkpoint 2

Add this route to your routes/web.php:

routes/web.php
php
Route::get('/check-models', function () {
$models = [
\App\Models\User::class,
\App\Models\Product::class,
\App\Models\Category::class,
\App\Models\Order::class,
\App\Models\OrderItem::class,
\App\Models\Review::class,
\App\Models\Wishlist::class,
];
$output = [];
foreach ($models as $model) {
$instance = new $model;
$relations = [];
$reflection = new ReflectionClass($instance);
foreach ($reflection->getMethods() as $method) {
if ($method->class == get_class($instance) && !$method->isStatic()) {
$methodName = $method->getName();
try {
$returnType = $method->getReturnType();
if ($returnType && (
strpos($returnType->getName(), 'Illuminate\Database\Eloquent\Relations') !== false ||
$returnType->getName() === 'Illuminate\Database\Eloquent\Relations\Relation'
)) {
$relations[] = $methodName;
} elseif (!$returnType) {
// Try to call the method to see if it returns a relation
$result = $instance->$methodName();
if (is_object($result) && method_exists($result, 'getRelated')) {
$relations[] = $methodName;
}
}
} catch (\Exception $e) {
// Skip if method can't be called without arguments
}
}
}
$output[class_basename($model)] = $relations;
}
return $output;
});

Visit /check-models and share a screenshot of the output on Slack. The output should show all your model relationships.