Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Eloquent Publishing Laravel Package

lemaur/eloquent-publishing

Add publishing support to Laravel Eloquent models with a simple trait. Manage publish dates, query scopes and helpers, plus custom migration blueprint methods to quickly add publishing columns and build publishable content workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require lemaur/eloquent-publishing
    
  2. Add the Publishes trait to your Eloquent model:
    use Lemaur\Publishing\Database\Eloquent\Publishes;
    
    class Post extends Model
    {
        use Publishes;
    }
    
  3. Add the publishes() column to your migration:
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->publishes(); // Adds `published_at` timestamp
    });
    

First Use Case

Publish a model immediately:

$post = Post::create(['title' => 'Hello World']);
$post->publish(); // Sets `published_at` to current timestamp

Implementation Patterns

Common Workflows

1. Publishing Logic in Controllers

// Publish with current timestamp
$post->publish();

// Publish at a future date
$post->publish(Carbon::parse('2025-12-31'));

// Unpublish
$post->unpublish();

2. Query Scopes for Filtering

// Get only published posts
$published = Post::onlyPublished()->get();

// Get upcoming (planned) posts
$planned = Post::onlyPlanned()->get();

// Combine scopes
$activePosts = Post::onlyPlannedAndPublished()->latestPublished()->get();

3. Migration Patterns

// Default (nullable timestamp)
$table->publishes();

// Custom column name
$table->publishes('release_date');

// Timezone-aware
$table->publishesTz('scheduled_at');

// Drop column
$table->dropPublishes('release_date');

4. Event Listeners

// In EventServiceProvider
protected $listen = [
    'publishing' => [
        \App\Listeners\LogPublish::class,
    ],
    'published' => [
        \App\Listeners\NotifyEditor::class,
    ],
];

5. Custom Column Names

// Model
class Post extends Model
{
    use Publishes;

    const PUBLISHED_AT = 'publication_date';
}

// Migration
$table->publishes('publication_date');

Gotchas and Tips

Pitfalls

  1. Column Name Mismatch:

    • If PUBLISHED_AT is defined in the model but the migration uses a different name, queries will fail.
    • Fix: Ensure consistency between model and migration.
  2. Timezone Issues:

    • publishes() uses timestamp, while publishesTz() uses timestampTz. Mixing these may cause serialization errors.
    • Fix: Stick to one type per model.
  3. Null Checks:

    • isPublished() returns true if published_at is not null (past or future). Use isPlanned() to check for future dates.
    • Tip: Chain with whereDate() for precise filtering:
      Post::whereNotNull('published_at')->where('published_at', '>=', now());
      
  4. Ordering Quirks:

    • latestPublished() sorts by published_at ascending by default. Use oldestPublished() for descending.
    • Fix: Verify order with dd($query->toSql()).

Debugging Tips

  • Check Events: Listen for publishing/published events to debug timing:
    event(new Publishing($post));
    
  • Query Logs: Enable query logging to verify scopes:
    DB::enableQueryLog();
    Post::onlyPublished()->get();
    dd(DB::getQueryLog());
    

Extension Points

  1. Custom Logic in Events: Extend the publishing event to validate content before publishing:

    public function handle(Publishing $event)
    {
        if (!$event->model->isValid()) {
            throw new \Exception('Invalid content!');
        }
    }
    
  2. Add Soft Publishing: Combine with SoftDeletes for "unpublish" as soft delete:

    use Illuminate\Database\Eloquent\SoftDeletes;
    
    class Post extends Model
    {
        use Publishes, SoftDeletes;
    
        public function unpublish()
        {
            $this->delete(); // Soft delete
        }
    }
    
  3. Override Default Column: Dynamically set the column name in the trait:

    // In Publishes trait
    protected static function getPublishedAtColumn()
    {
        return config('eloquent-publishing.column', 'published_at');
    }
    

Configuration Quirks

  • No Config File: The package relies on model constants (PUBLISHED_AT) or migration arguments. No config/eloquent-publishing.php exists.
  • Precision Handling: The publishes() method accepts a precision parameter (e.g., $table->publishes('published_at', 3)), but this is rarely needed for timestamps.

Performance Tips

  • Index the Column: Add an index in migrations for faster queries:
    $table->publishes('published_at');
    $table->index('published_at');
    
  • Avoid N+1 in Scopes: Use with() or load() when eager-loading related models in scopes:
    Post::onlyPublished()->with('author')->get();
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky