Installation
composer require avris/esse
php artisan vendor:publish --provider="Avris\Esse\EsseServiceProvider" --tag="config"
php artisan migrate
First Use Case: Basic Page Creation
Avris\Esse\Contracts\PageContract:
use Avris\Esse\Contracts\PageContract;
class BlogPost extends PageContract
{
protected $title = 'Blog Post';
}
config/esse.php under pages.$post = \App\Models\BlogPost::create(['title' => 'First Post', 'slug' => 'first-post']);
$post->content()->create(['body' => '<h1>Hello World</h1>']);
Key Files to Review
config/esse.php: Core configuration (page models, routes, etc.).app/Models/Page.php: Base page model (extend this for custom logic).resources/views/vendor/esse/: Default templates (override as needed).CRUD via Eloquent:
// Create
$page = \App\Models\BlogPost::create(['slug' => 'new-post']);
// Fetch with content
$page = \App\Models\BlogPost::withContent()->find($id);
// Update
$page->update(['title' => 'Updated Title']);
$page->content()->update(['body' => '<p>New content</p>']);
// Delete (soft delete enabled by default)
$page->delete();
Slug Handling:
Use Avris\Esse\Traits\HasSlug for automatic slug generation:
class BlogPost extends PageContract
{
use HasSlug;
protected $slugField = 'title'; // Auto-generate slug from title
}
Rich Text with Markdown:
Store content in a content morph-to relationship:
$post->content()->create([
'body' => '# Markdown Title',
'type' => \Avris\Esse\Models\Content::TYPE_MARKDOWN
]);
Render in Blade:
{!! $page->content->render() !!}
Media Attachments:
Use Avris\Esse\Traits\HasMedia to attach files/images:
$post->addMedia($file)->toMediaCollection('images');
Auto-Routing:
Enable in config/esse.php:
'routes' => [
'enabled' => true,
'prefix' => 'pages',
],
Generates routes like /pages/{slug}.
Custom Controllers:
Extend Avris\Esse\Http\Controllers\PageController:
namespace App\Http\Controllers;
use Avris\Esse\Http\Controllers\PageController as BasePageController;
class PageController extends BasePageController
{
protected $pageModel = \App\Models\BlogPost::class;
}
Override Default Views: Publish and modify views:
php artisan vendor:publish --tag="esse-views"
Example: resources/views/vendor/esse/page.blade.php.
Dynamic Layouts:
Use page_layout field in the database to switch layouts:
$page->update(['page_layout' => 'custom-layout']);
JSON:API Compliance:
Use Avris\Esse\Http\Resources\PageResource:
use Avris\Esse\Http\Resources\PageResource;
return PageResource::collection($pages);
GraphQL:
Install avris/esse-graphql for GraphQL support:
composer require avris/esse-graphql
Slug Conflicts:
slug is unique. Use HasSlug trait for auto-generation:
use Avris\Esse\Traits\HasSlug;
\Avris\Esse\Services\SlugService::generate('Title', \App\Models\BlogPost::class);
Content Relationships:
$pages = \App\Models\BlogPost::withContent()->get();
type field (e.g., markdown, html).Route Caching:
php artisan route:clear
Media Collections:
storage_link is set in config/filesystems.php for public access:
'links' => [
'public' => storage_path('app/public'),
],
php artisan storage:link if media isn’t appearing.Soft Deletes:
$page->restore();
$page->forceDelete();
Log Page Events:
Enable logging in config/esse.php:
'logging' => [
'enabled' => true,
'channel' => 'single',
],
Check storage/logs/laravel.log for page lifecycle events.
Query Debugging: Use Laravel Debugbar to inspect queries:
composer require barryvdh/laravel-debugbar
Common Errors:
type field matches a supported content handler (e.g., markdown, html).Custom Content Types:
Extend Avris\Esse\Models\Content or create a new morph map:
\Avris\Esse\Models\Content::addMorphMap([
'custom_content' => \App\Models\CustomContent::class,
]);
Page Events:
Listen to page events (e.g., page.created):
\Avris\Esse\Events\PageCreated::dispatch($page);
Register listeners in EventServiceProvider:
protected $listen = [
\Avris\Esse\Events\PageCreated::class => [
\App\Listeners\LogPageCreation::class,
],
];
Middleware:
Add middleware to page routes in app/Http/Kernel.php:
protected $routeMiddleware = [
'esse.auth' => \Avris\Esse\Http\Middleware\Authenticate::class,
];
Apply to routes:
Route::get('/pages/{slug}', [PageController::class, 'show'])
->middleware('esse.auth');
Validation Rules:
Extend validation in app/Providers/EsseServiceProvider.php:
public function boot()
{
\Avris\Esse\Validators\PageValidator::extend(function ($validator, $attribute, $value, $parameters) {
// Custom validation logic
});
}
Caching: Cache page queries with tags:
$page = \Avris\Esse\Facades\Esse::getPage($slug, true); // Force cache
Clear cache by tag:
php artisan cache:tags --tag=esse-pages --clear
Database Indexes:
Add indexes to slug and published_at fields for large datasets:
Schema::table('pages', function (Blueprint $table) {
$table->index('slug');
$table->index('published_at');
});
Lazy Loading:
Use withContent() selectively to avoid loading unnecessary content:
$pages = \App\Models\BlogPost::where('published_at', '<', now())->get();
// Only load content for specific pages
$pages->where('id', $id)->withContent()->first();
How can I help you explore Laravel packages today?