Installation
composer require chill-project/chill-doc-store
php artisan vendor:publish --provider="Chill\DocStore\DocStoreServiceProvider" --tag="config"
php artisan migrate
doc_store table exists in your database.First Use Case: Uploading a Document
use Chill\DocStore\Models\Document;
$document = Document::create([
'title' => 'Project Proposal',
'description' => 'Q3 2024 Proposal',
'file_path' => 'documents/project-proposal.pdf', // Relative to storage/app/public
'mime_type' => 'application/pdf',
'size' => 2048, // in KB
]);
storage/app/public/documents is symlinked to public/documents:
php artisan storage:link
Retrieving a Document
$document = Document::find(1);
$filePath = $document->getFullPath(); // Returns full public URL
File Upload Handling
Chill\DocStore\Services\DocumentUploader service for automated uploads:
use Chill\DocStore\Services\DocumentUploader;
$uploader = app(DocumentUploader::class);
$result = $uploader->upload(
file: $request->file('document'),
metadata: ['title' => 'Contract', 'client_id' => 123]
);
// Returns Document model or throws exception
Versioning Documents
config/doc-store.php:
'versioning' => true,
$document->versions()->latest()->first();
Access Control
Document model (e.g., DocumentPolicy):
use Chill\DocStore\Models\Document;
class DocumentPolicy
{
public function download(User $user, Document $document)
{
return $user->hasRole('admin') || $document->user_id === $user->id;
}
}
Events and Observers
DocumentCreated):
Document::created(function ($document) {
// Send notification, log, etc.
});
Laravel Filesystem
config/doc-store.php:
'disk' => 's3', // Use 's3', 'local', or custom disk
's3' => [
'bucket' => 'my-documents-bucket',
],
API Responses
namespace App\Http\Resources;
use Chill\DocStore\Models\Document;
use Illuminate\Http\Resources\Json\JsonResource;
class DocumentResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'url' => $this->getFullPath(),
'size' => $this->size,
'created_at' => $this->created_at->toIso8601String(),
];
}
}
Frontend Integration
document-url helper in Blade:
<a href="{{ document_url($document) }}" download>Download</a>
File Paths
storage_path() instead of using Document::getFullPath().getFullPath() for public URLs to handle symlinks/config changes.Mime Type Detection
mime_type can break downloads or security checks.mime-type package or validate manually:
$mime = mime_content_type($file->getPathname());
Versioning Overhead
// app/Console/Commands/CleanupDocVersions.php
Document::where('created_at', '<', now()->subMonths(6))
->each(function ($doc) {
$doc->versions()->where('created_at', '<', now()->subMonths(3))->delete();
});
Concurrent Uploads
$path = "documents/{$document->id}_{$document->title}_{time()}.{$extension}";
Missing Files
storage/app/public/documents symlink exists.chmod -R 755 storage/app/public).config/doc-store.php disk settings.Slow Queries
doc_store table:
Schema::table('doc_store', function (Blueprint $table) {
$table->index('user_id');
$table->index('mime_type');
});
Custom Storage Logic
Chill\DocStore\Services\DocumentUploader class to add pre/post-upload logic:
class CustomDocumentUploader extends DocumentUploader
{
protected function beforeUpload(Document $document, $file)
{
// Add watermark, validate size, etc.
}
}
$this->app->bind(DocumentUploader::class, CustomDocumentUploader::class);
Metadata Fields
Document model to add custom fields:
class Document extends \Chill\DocStore\Models\Document
{
protected $casts = [
'tags' => 'array',
'expiry_date' => 'datetime',
];
}
Webhooks
Document::created(function ($document) {
Http::post('https://webhook.example.com/documents', [
'document_id' => $document->id,
'title' => $document->title,
]);
});
How can I help you explore Laravel packages today?