Installation
composer require xlabs/articlebundle
Publish the bundle’s assets and configuration:
php artisan vendor:publish --provider="Xlabs\ArticleBundle\ArticleServiceProvider" --tag="config"
php artisan vendor:publish --provider="Xlabs\ArticleBundle\ArticleServiceProvider" --tag="migrations"
php artisan migrate
First Use Case: Creating an Article
Register the bundle in config/app.php under providers:
Xlabs\ArticleBundle\ArticleServiceProvider::class,
Define a route in routes/web.php:
use Xlabs\ArticleBundle\Http\Controllers\ArticleController;
Route::resource('articles', ArticleController::class);
Test by visiting /articles/create and submitting a form with required fields (title, content, slug).
config/article.php (adjust default settings like storage paths, allowed categories, or SEO rules).database/migrations/[timestamp]_create_articles_table.php (customize columns or add indexes).src/Http/Controllers/ArticleController.php (extend or override methods like store() or update()).resources/views/vendor/article/ (customize Blade templates for article listings, details, or forms).CRUD Operations
Use the built-in ArticleController for basic operations. Extend it for custom logic:
namespace App\Http\Controllers;
use Xlabs\ArticleBundle\Http\Controllers\ArticleController as BaseArticleController;
use App\Models\Article;
class ArticleController extends BaseArticleController
{
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique:articles|max:255',
'content' => 'required',
'category' => 'required|exists:categories,id',
]);
return parent::store($request);
}
}
Custom Fields
Add fields to the articles table via migrations, then extend the Article model:
namespace App\Models;
use Xlabs\ArticleBundle\Models\Article as BaseArticle;
class Article extends BaseArticle
{
protected $casts = [
'is_featured' => 'boolean',
'publish_date' => 'datetime',
];
}
API Integration Use Laravel’s API resources to format responses:
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use Xlabs\ArticleBundle\Models\Article;
class ArticleResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'excerpt' => Str::limit($this->content, 100),
'meta' => [
'author' => $this->author->name,
'published_at' => $this->published_at->toDateTimeString(),
],
];
}
}
Event Listeners
Subscribe to article events (e.g., ArticleCreated) in EventServiceProvider:
protected $listen = [
'Xlabs\ArticleBundle\Events\ArticleCreated' => [
'App\Listeners\SendArticleNotification',
],
];
@articleList, @articleDetail) in your templates.config/article.php to use Laravel’s spatie/laravel-medialibrary for article images:
'media' => [
'driver' => 'spatie',
'model' => App\Models\Article::class,
],
generateSlug method in the Article model to enforce custom rules:
public function generateSlug()
{
return Str::slug($this->title . ' ' . $this->id);
}
resources/lang/vendor/article) for multi-language support.Slug Conflicts
save() method in the Article model to enforce uniqueness:
public function save(array $options = [])
{
$this->slug = $this->generateSlug();
$this->ensureSlugIsUnique();
return parent::save($options);
}
Missing Migrations
php artisan vendor:publish --tag="migrations" after installation or updates.Caching Headaches
php artisan view:clear
php artisan route:clear
php artisan cache:clear
Permission Denied
app/Http/Kernel.php:
protected $middlewareGroups = [
'web' => [
// ...
\Xlabs\ArticleBundle\Http\Middleware\VerifyArticleOwnership::class,
],
];
Log Article Events: Enable logging for article events in config/logging.php:
'channels' => [
'article_events' => [
'driver' => 'single',
'path' => storage_path('logs/article_events.log'),
'level' => 'debug',
],
],
Then subscribe in EventServiceProvider:
protected $listen = [
'Xlabs\ArticleBundle\Events\*' => [
'App\Listeners\LogArticleEvent',
],
];
Query Debugging: Use Laravel Debugbar to inspect queries:
composer require barryvdh/laravel-debugbar
Then check the "Queries" tab for slow or unexpected queries.
Custom Article Types Use trait composition to add behavior:
namespace App\Models;
use Xlabs\ArticleBundle\Models\Concerns\HasCategories;
use Xlabs\ArticleBundle\Models\Concerns\HasTags;
class Article extends \Xlabs\ArticleBundle\Models\Article
{
use HasCategories, HasTags;
}
Dynamic Validation
Extend the ArticleRequest class:
namespace App\Http\Requests;
use Xlabs\ArticleBundle\Http\Requests\ArticleRequest as BaseArticleRequest;
class ArticleRequest extends BaseArticleRequest
{
public function rules()
{
$rules = parent::rules();
$rules['featured_image'] = 'required_if:is_featured,true';
return $rules;
}
}
API Versioning Use Laravel’s API versioning to maintain backward compatibility:
Route::prefix('api/v1')->group(function () {
Route::resource('articles', \App\Http\Controllers\V1\ArticleController::class);
});
Testing
Use the bundle’s test helpers in phpunit.xml:
<env name="ARTICLE_BUNDLE_TESTING" value="true"/>
Then leverage factories in database/factories/ArticleFactory.php:
$article = Article::factory()->create([
'title' => 'Test Article',
'content' => 'Test content',
]);
How can I help you explore Laravel packages today?