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

Paragraphs Laravel Package

braunstetter/paragraphs

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require braunstetter/paragraphs
    

    Publish the migration and config:

    php artisan vendor:publish --provider="Braunstetter\Paragraphs\ParagraphsServiceProvider"
    php artisan migrate
    
  2. Basic Model Setup Extend your model with HasParagraphs trait:

    use Braunstetter\Paragraphs\HasParagraphs;
    
    class Post extends Model
    {
        use HasParagraphs;
    }
    
  3. First Use Case Define paragraphs in a migration:

    Schema::create('paragraphs', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('content');
        $table->foreignId('post_id')->constrained()->onDelete('cascade');
        $table->timestamps();
    });
    

    Create a paragraph via Tinker:

    $post = Post::first();
    $post->paragraphs()->create(['title' => 'Intro', 'content' => 'Hello world!']);
    

Implementation Patterns

Workflow: CRUD with Paragraphs

  1. Create

    $post = Post::create(['title' => 'New Post']);
    $post->paragraphs()->createMany([
        ['title' => 'Section 1', 'content' => 'Content...'],
        ['title' => 'Section 2', 'content' => 'More content...'],
    ]);
    
  2. Read

    // Eager-load paragraphs with the post
    $post = Post::with('paragraphs')->find(1);
    
    // Access paragraphs
    foreach ($post->paragraphs as $paragraph) {
        echo $paragraph->title . ': ' . $paragraph->content;
    }
    
  3. Update

    $paragraph = $post->paragraphs->first();
    $paragraph->update(['content' => 'Updated content']);
    
  4. Delete

    $paragraph->delete(); // Soft deletes if using SoftDeletes trait
    

Integration with Forms

Use paragraphs relationship in Form Requests:

public function rules()
{
    return [
        'paragraphs.*' => 'required|array',
        'paragraphs.*.title' => 'required|string|max:255',
        'paragraphs.*.content' => 'required|string',
    ];
}

Dynamic Paragraph Types

Extend the package for custom paragraph types (e.g., ImageParagraph, VideoParagraph):

class Post extends Model
{
    use HasParagraphs;

    protected $paragraphTypes = [
        'text' => \Braunstetter\Paragraphs\Models\TextParagraph::class,
        'image' => \App\Models\ImageParagraph::class,
    ];
}

Gotchas and Tips

Pitfalls

  1. Missing Foreign Key Ensure the paragraphs table has a foreign key column (e.g., post_id) matching your model’s primary key. The package assumes a paragraphable_id column by default—customize via $paragraphableType in config.

  2. Mass Assignment Risks Paragraphs are created via create() or createMany(), which may expose sensitive fields. Whitelist allowed fields in your model:

    protected $guarded = [];
    protected $fillable = ['title', 'content'];
    
  3. Ordering Issues Paragraphs lack a default order column. Add one if ordering matters:

    Schema::table('paragraphs', function (Blueprint $table) {
        $table->integer('order')->default(0);
    });
    

    Then sort in queries:

    $post->paragraphs()->orderBy('order');
    

Debugging

  • Missing Paragraphs? Check if the relationship is properly defined in your model and if the foreign key exists in the database.

  • Soft Deletes If using SoftDeletes, ensure the paragraphs table has deleted_at and your queries include withTrashed():

    $post->paragraphs()->withTrashed()->get();
    

Extension Points

  1. Custom Paragraph Models Override the default Paragraph model by binding your own in the service provider:

    $this->app->bind(
        \Braunstetter\Paragraphs\Models\Paragraph::class,
        \App\Models\CustomParagraph::class
    );
    
  2. Event Hooks Listen for paragraph events (e.g., paragraph.created) to trigger side effects:

    \Braunstetter\Paragraphs\Models\Paragraph::created(function ($paragraph) {
        // Log or notify when a paragraph is created
    });
    
  3. API Resources Create a dedicated ParagraphResource for API responses:

    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'content' => Str::limit($this->content, 200),
            'type' => 'text',
        ];
    }
    

Config Quirks

  • Default Paragraph Model The package uses Braunstetter\Paragraphs\Models\Paragraph by default. Customize in config/paragraphs.php:

    'model' => \App\Models\CustomParagraph::class,
    
  • Polymorphic Relationships For polymorphic paragraphs (e.g., shared across Post and Page), set:

    'polymorphic' => true,
    

    Then define the relationship in your models:

    public function paragraphs()
    {
        return $this->morphMany(\Braunstetter\Paragraphs\Models\Paragraph::class, 'paragraphable');
    }
    
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.
gsferro/filament-odometer-easy
gsferro/filament-stat-plus-easy
jeffersongoncalves/filament-barcode-field
martin6363/filament-sidebar-resize
graystackit/laravel-dymo-printer
phpinnacle/money
lastdragon-ru/lara-asp-documentator
tumutech/laravel-qr-code
babenkoivan/elastic-scout-driver-plus
socialiteproviders/apple
phpshko/laravel-livewire-depdrop
larasell-dev/larasell
calliostro/spotify-bundle
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle