Weave 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

Doc Laravel Package

bfg/doc

A Laravel/PHP documentation package from BFG that helps generate and organize project documentation, making it easy to browse and maintain reference docs alongside your codebase.

View on GitHub
Deep Wiki
Context7

Getting Started

Because this package has a single star and no dependents, treat the first ten minutes as an audit rather than a normal install. Pin the exact version you evaluate — do not use ^1.0.

composer require bfg/doc:1.x.y   # exact version, note it in your PR description

Then, in order:

  1. Read composer.json in vendor/bfg/doc first. Check the require block for the PHP and illuminate/* constraints. If it declares laravel/framework: ^8.0 and you are on Laravel 11, stop and decide whether a fork is cheaper than adoption.
  2. Inspect src/ before running anything. With one star, the source is the documentation. Look for the service provider (auto-discovery or manual registration), the config/ file name, any database/migrations/ stubs, and whether routes/views are shipped.
  3. Publish only what you need, using tags if they exist:
php artisan vendor:publish --provider="Bfg\Doc\DocServiceProvider"
# or, if tags are defined:
php artisan vendor:publish --tag=doc-config
php artisan vendor:publish --tag=doc-migrations
  1. Diff the published config against the vendor copy — package authors in low-traffic repos sometimes ship a config that contradicts the code's defaults.
  2. Run php artisan migrate on a scratch database and inspect the resulting schema. Column names and index choices tell you more about intended usage than the README will.

First use case: the lowest-risk integration is read-only. Point the package at an existing documents table or a small Storage disk folder, render one listing, and verify the query path before you let it write anything. Once the read path is understood, add a single create flow behind a feature flag.

If the README is empty or aspirational, budget an hour to write your own usage note in the repo wiki the day you adopt it. You will be the only source of documentation for your team.

Implementation Patterns

Wrap it, don't scatter it. Create one application-level service (App\Services\DocumentService) that owns every call into the package. Models, controllers, and jobs talk to your service. When the package is abandoned — a realistic outcome at one star — you replace one file instead of grepping fifty.

final class DocumentService
{
    public function __construct(private DocumentRepository $docs) {}

    public function attach(Model $owner, UploadedFile $file, array $meta = []): Document
    {
        return DB::transaction(function () use ($owner, $file, $meta) {
            $path = $file->store("documents/{$owner->getKey()}", 'documents');

            return $this->docs->create([
                'owner_type' => $owner->getMorphClass(),
                'owner_id'   => $owner->getKey(),
                'path'       => $path,
                'name'       => $file->getClientOriginalName(),
                'mime'       => $file->getMimeType(),
                'size'       => $file->getSize(),
                ...$meta,
            ]);
        });
    }
}

Keep the polymorphic shape if it exists. If the package ships documentable_type / documentable_id, preserve it exactly rather than adding your own user_id columns. It lets you attach documents to invoices, tickets, and users with one table, and it keeps future package upgrades from breaking your schema.

Isolate the storage disk. Register a dedicated disk (private, not public) and reference it by name in config. Never let the package fall back to the default disk — the day someone changes FILESYSTEM_DISK in .env, every stored document path breaks silently.

// config/filesystems.php
'documents' => [
    'driver' => 's3',
    'root'   => 'tenant-' . tenant('id') . '/documents',
    // ...
],

Serve downloads through a controller, not a URL. Even if the package exposes a route, add your own authorization check in front of it:

public function download(Document $document)
{
    $this->authorize('view', $document);

    return Storage::disk($document->disk)->download($document->path, $document->name);
}

Enforce validation at the edge. File size, MIME type, and extension checks belong in a FormRequest, not in the package's config file — config is global, and you will eventually need a 50MB upload for one tenant and 5MB for everyone else.

'file' => ['required', 'file', 'max:10240', 'mimes:pdf,docx,xlsx,png'],

Test with Storage::fake() and an in-memory database. Because there is no community test suite behind this package, your own suite is the regression net. A single feature test covering upload → list → download → delete will catch nearly every breaking change an upgrade introduces.

Introduce a thin adapter if the API is thin. If the package is essentially a model plus a migration, do not fight it — subclass or use its trait, and add the behaviour you need (versioning, soft deletes, virus scanning) in your own layer so a later replacement is a no-op.

Gotchas and Tips

  • Bus factor is one. One star and zero dependents means: no issue triage, no security advisories, no upgrade path. Fork it into your VCS on day one, even if you never change a line. composer require against a VCS path is cheap insurance.
  • Lock the version and audit on update. Set "bfg/doc": "1.2.3" in composer.json, and put a comment in the PR explaining why. A caret range on an unmaintained package is a supply-chain decision you did not consciously make.
  • Orphaned files are the default failure mode. DB::transaction cannot roll back a file write. Upload first, insert second, and schedule a nightly reconciliation job that deletes files with no row and flags rows with no file. Do the delete in the opposite order: soft-delete the record, remove the file, then hard-delete in a queued job.
  • Migration collisions. Published migrations are timestamped at publish time, not at authoring time. If the package assumes a users table created in 2014 and you publish today, the foreign key may run before users exists. Rename the published migration file to reorder it.
  • Config caching bites on deploy. php artisan config:cache freezes package config at build time. If the package reads an env var inside a class rather than in config/doc.php, you will see stale values in production that never appear locally. Grep env( in vendor/bfg/doc/src — any hit is a latent bug.
  • Check what the provider registers eagerly. If it publishes global routes, a facade binding, or a view namespace, a later framework upgrade that changes provider boot ordering can break unrelated parts of your app. Guard by running the app with package disabled once; anything that breaks your build was coupled to it.
  • Model binding and auth. If the package exposes route-model-bound endpoints, confirm it applies your middleware group. Routes registered inside a provider do not inherit the middleware of your routes/web.php. Check with php artisan route:list --path=doc.
  • vendor/ diffing is your changelog. Since no release notes are likely, diff vendor/bfg/doc between versions before upgrading. git diff --no-index on the vendor directory after composer update shows exactly what moved.
  • Extension points are limited — plan to shadow. If there is no contract or repository interface, you cannot decorate it cleanly. Prefer overriding views and config over subclassing internals; internal classes in a one-star package are not part of any stability promise.
  • Debugging checklist when something silently does nothing: php artisan config:clear && route:clear, confirm the provider is listed in bootstrap/providers.php (Laravel 11) or config/app.php (10 and below), confirm the published migration actually ran (php artisan migrate:status), and log a call to the package's entry point to verify it is invoked at all.
  • Have an exit plan on paper. The realistic replacement is a 150-line Document model with a morph relation and a storage disk. Write down what that migration looks like while the package is fresh in your head — it turns an emergency into an afternoon.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons