PHPackages                             jonhassall/belongs-to-user-or-guest - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. jonhassall/belongs-to-user-or-guest

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

jonhassall/belongs-to-user-or-guest
===================================

Trait for models that can belong to either a user or a guest session

v1.0.2(3w ago)117MITPHP

Since Jan 13Pushed 3w agoCompare

[ Source](https://github.com/jonhassall/BelongsToUserOrGuest)[ Packagist](https://packagist.org/packages/jonhassall/belongs-to-user-or-guest)[ RSS](/packages/jonhassall-belongs-to-user-or-guest/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (6)Versions (5)Used By (0)

BelongsToUserOrGuest
====================

[](#belongstouserorguest)

A Laravel package that provides traits for Eloquent models to support ownership by either authenticated users or guest sessions. This is perfect for applications where you want to allow both logged-in users and guests to interact with your application - for example, shopping carts, wishlists, favorites, or any feature that should work without requiring users to sign up first.

Features
--------

[](#features)

### BelongsToUserOrGuest Trait

[](#belongstouserorguest-trait)

Attach this trait to any model that can belong to either a logged-in user or a guest session.

**Key Features:**

- **Automatic Assignment**: Automatically assign models to the current user or guest session
- **Ownership Check**: Check if a model belongs to the current request
- **Query Scopes**: Retrieve only models owned by the current user or guest
- **Guest-to-User Migration**: Move guest-owned models to a user account when they log in
- **Flexible Relationships**: Support for custom guest model classes and foreign keys

### IsGuest Trait

[](#isguest-trait)

Attach this trait to your guest session model to manage guest sessions with cookie-based tracking.

**Key Features:**

- **Cookie Handling**: Persistent cookies to track guests across visits
- **IP Tracking**: Optional IP address storage for security or analytics
- **Session Cleanup**: Remove old, expired guest sessions
- **Caching**: Request-level caching for performance
- **Configurable**: Customizable cookie names, durations, and behaviors

Requirements
------------

[](#requirements)

- **Laravel:** 10.x through 13.x
- **PHP:** 8.1 or higher
- **Cookies:** This package uses cookies to track guest sessions and does not require Laravel's session driver to be configured. All guest session management is handled entirely through cookies, making it lightweight and independent of your application's session configuration.

Installation
------------

[](#installation)

### Option 1: Via Packagist (Recommended)

[](#option-1-via-packagist-recommended)

Install the package via Composer:

```
composer require jonhassall/belongs-to-user-or-guest
```

### Option 2: Install Directly from GitHub

[](#option-2-install-directly-from-github)

You can install it directly from the GitHub repository. Add this to your `composer.json`:

```
{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/jonhassall/BelongsToUserOrGuest.git"
        }
    ],
    "require": {
        "jonhassall/belongs-to-user-or-guest": "dev-main"
    }
}
```

Then run:

```
composer install
```

Versioning and Branches
-----------------------

[](#versioning-and-branches)

- Stable releases use semantic version tags, for example: `v1.0.2`
- The `main` branch is the primary development branch
- Composer branch alias maps `dev-main` to `1.x-dev` for users tracking development
- Patch releases should branch from `main`, then be tagged and pushed

Release example:

```
git checkout main
git pull origin main
git tag -a v1.0.2 -m "Release v1.0.2"
git push origin main --tags
```

Full release checklist: [RELEASE\_CHECKLIST.md](RELEASE_CHECKLIST.md)

Quick Start
-----------

[](#quick-start)

### Step 1: Set Up Your Guest Model

[](#step-1-set-up-your-guest-model)

Create a migration for your guest sessions table:

```
php artisan make:migration create_guests_table
```

```
Schema::create('guests', function (Blueprint $table) {
    $table->id();
    $table->string('session_token')->unique();
    $table->string('ip_address')->nullable(); // Optional
    $table->timestamps();
});
```

Create your Guest model:

```
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use JonHassall\BelongsToUserOrGuest\IsGuest;

class Guest extends Model
{
    use IsGuest;

    protected $fillable = ['session_token', 'ip_address'];

    // Required: Cookie name for guest sessions
    protected function getCookieName(): string
    {
        return 'guest_session';
    }

    // Optional: Cookie duration in minutes (default: 1 year)
    protected function getCookieDuration(): int
    {
        return 525600; // 1 year
    }

    // Optional: Store guest IP addresses
    protected function shouldStoreIP(): bool
    {
        return true;
    }
}
```

### Step 2: Set Up Your Resource Model

[](#step-2-set-up-your-resource-model)

Add the necessary columns to your resource table:

```
Schema::create('favorites', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->nullable()->constrained()->onDelete('cascade');
    $table->foreignId('guest_id')->nullable()->constrained()->onDelete('cascade');
    $table->string('item_name');
    $table->timestamps();
});
```

Add the trait to your model:

```
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use JonHassall\BelongsToUserOrGuest\BelongsToUserOrGuest;

class Favorite extends Model
{
    use BelongsToUserOrGuest;

    protected $fillable = ['item_name', 'user_id', 'guest_id'];

    // Required: Specify your guest model class
    protected function getGuestModel(): string
    {
        return Guest::class;
    }

    // Optional: Custom foreign key (default: 'guest_id')
    protected function getGuestForeignKey(): string
    {
        return 'guest_id';
    }
}
```

Usage Examples
--------------

[](#usage-examples)

### Creating Records with Ownership

[](#creating-records-with-ownership)

```
// Method 1: Create and assign manually
$favorite = new Favorite(['item_name' => 'Laravel']);
$favorite->assignToCurrentOwner(); // Automatically assigns to user or guest

// Method 2: Create with ownership in one step
$favorite = Favorite::createWithOwnership([
    'item_name' => 'Laravel'
]);

// Method 3: Update or create with ownership
$favorite = Favorite::updateOrCreateWithOwnership(
    ['item_name' => 'Laravel'], // Search criteria
    ['updated_at' => now()]      // Additional values
);
```

### Querying Records

[](#querying-records)

```
// Get all favorites for current user or guest
$favorites = Favorite::forCurrentOwner()->get();

// Check if a specific favorite belongs to current user/guest
if ($favorite->isOwnedByCurrentRequest()) {
    // Allow editing or deletion
}

// Access the owner (returns User or Guest model)
$owner = $favorite->owner;
```

### Migrating Guest Data to User Account

[](#migrating-guest-data-to-user-account)

When a guest logs in or signs up, transfer their data:

```
// Option 1: In your login/registration controller
use App\Models\Favorite;
use App\Models\Guest;

public function login(Request $request)
{
    // After successful authentication...

    // Move all guest favorites to the logged-in user
    Favorite::moveGuestToUser($request);

    // Optionally delete the guest session
    Guest::deleteGuestSession($request);
}
```

```
// Option 2: Automatically on login using AppServiceProvider
// In app/Providers/AppServiceProvider.php

use Illuminate\Support\Facades\Event;
use Illuminate\Auth\Events\Login;
use App\Models\Favorite;
use App\Models\ShoppingCart;
use App\Models\Guest;

public function boot(): void
{
    // Automatically move guest data when user logs in
    Event::listen(function (Login $event) {
        // Move guest-owned models to the logged-in user
        Favorite::moveGuestToUser();

        // Delete the guest session after migrating data
        Guest::deleteGuestSession();

        // Optional: Notify the user their data was saved
        if (request()->hasSession()) {
            session()->flash('success', 'Your favorites and cart have been saved to your account.');
        }
    });
}
```

### Working with Guest Sessions Directly

[](#working-with-guest-sessions-directly)

```
use App\Models\Guest;

// Get or create guest for current request
$guest = Guest::getOrCreateGuest();

// Check if current request is a guest (not logged in)
if (Guest::isGuest()) {
    // Show guest-specific messaging
}

// Get current user or guest
$currentOwner = Guest::getCurrentUserOrGuest();

// Clean up old guest sessions (run in scheduled task)
$deletedCount = Guest::cleanup();
```

### Advanced Usage

[](#advanced-usage)

```
// Create without auto-saving
$favorite = new Favorite(['item_name' => 'Vue']);
$favorite->assignToCurrentOwner(persist: false); // Don't save yet
$favorite->some_other_field = 'value';
$favorite->save(); // Save when ready

// Remove ownership
$favorite->removeOwnership(); // Clears both user_id and guest_id

// Query scopes with explicit request
$favorites = Favorite::forCurrentOwner($customRequest)->get();
```

Method Reference
----------------

[](#method-reference)

### BelongsToUserOrGuest Methods

[](#belongstouserorguest-methods)

MethodDescription`assignToCurrentOwner(?Request $request, bool $persist = true)`Assign model to current user or guest`removeOwnership(bool $persist = true)`Clear ownership from model`isOwnedByCurrentRequest(?Request $request)`Check if current user/guest owns this model`scopeForCurrentOwner($query, ?Request $request)`Query scope for current owner's models`moveGuestToUser(?Request $request)`Transfer all guest models to logged-in user`createWithOwnership(array $data, ?Request $request)`Create model with ownership in one step`updateOrCreateWithOwnership(array $attributes, array $values, ?Request $request)`Update or create with ownership`user()`Relationship to User model`guest()`Relationship to Guest model`owner`Attribute accessor for current owner (User or Guest)### IsGuest Methods

[](#isguest-methods)

MethodDescription`getOrCreateGuest(?Request $request, bool $createIfNeeded = true)`Get or create guest session`getGuest(?Request $request, bool $createIfNeeded, bool $ignoreLoggedIn)`Get guest session with options`getCurrentUserOrGuest(?Request $request, bool $createIfNeeded)`Get authenticated user or guest`isGuest(?Request $request)`Check if request is from a guest`deleteGuestSession(?Request $request)`Delete guest session and cookie`cleanup()`Remove expired guest sessionsConfiguration
-------------

[](#configuration)

### Required Abstract Methods

[](#required-abstract-methods)

**BelongsToUserOrGuest:**

- `getGuestModel(): string` - Return the fully qualified class name of your guest model

**IsGuest:**

- `getCookieName(): string` - Return the cookie name for guest sessions

### Optional Configuration Methods

[](#optional-configuration-methods)

**BelongsToUserOrGuest:**

- `getGuestForeignKey(): string` - Foreign key column name (default: `'guest_id'`)

**IsGuest:**

- `getCookieDuration(): int` - Cookie lifetime in minutes (default: 525600 = 1 year)
- `shouldStoreIP(): bool` - Enable IP address storage (default: false)

Database Schema Requirements
----------------------------

[](#database-schema-requirements)

### Resource Table (e.g., favorites)

[](#resource-table-eg-favorites)

```
$table->foreignId('user_id')->nullable()->constrained()->onDelete('cascade');
$table->foreignId('guest_id')->nullable()->constrained('guests')->onDelete('cascade');
```

### Guest Table

[](#guest-table)

```
$table->id();
$table->string('session_token')->unique();
$table->string('ip_address')->nullable(); // If using shouldStoreIP()
$table->timestamps();
```

Scheduled Tasks
---------------

[](#scheduled-tasks)

Add to `app/Console/Kernel.php` to clean up old guest sessions:

```
protected function schedule(Schedule $schedule)
{
    $schedule->call(function () {
        \App\Models\Guest::cleanup();
    })->daily();
}
```

License
-------

[](#license)

This package is open-sourced software licensed under the MIT license.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance94

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity38

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~74 days

Total

3

Last Release

25d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/9570507?v=4)[Jonathan Hassall](/maintainers/jonhassall)[@jonhassall](https://github.com/jonhassall)

---

Top Contributors

[![jonhassall](https://avatars.githubusercontent.com/u/9570507?v=4)](https://github.com/jonhassall "jonhassall (8 commits)")

### Embed Badge

![Health badge](/badges/jonhassall-belongs-to-user-or-guest/health.svg)

```
[![Health](https://phpackages.com/badges/jonhassall-belongs-to-user-or-guest/health.svg)](https://phpackages.com/packages/jonhassall-belongs-to-user-or-guest)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[mike-bronner/laravel-model-caching

Automatic caching for Eloquent models.

2.4k91.9k1](/packages/mike-bronner-laravel-model-caching)[api-platform/laravel

API Platform support for Laravel

58171.8k14](/packages/api-platform-laravel)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45444.2k1](/packages/pressbooks-pressbooks)[hasinhayder/tyro

Tyro - The ultimate Authentication, Authorization, and Role &amp; Privilege Management solution for Laravel 12 &amp; 13

6804.7k6](/packages/hasinhayder-tyro)[masterix21/laravel-licensing

Laravel licensing package with polymorphic assignment to any model, activation keys, expirations/renewals, and seat control via LicenseUsage. Supports offline verification with public-key–signed tokens, a CLI to generate/rotate/revoke keys, and an extensible architecture via config and contracts.

1563.2k4](/packages/masterix21-laravel-licensing)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
