PHPackages                             univpancasila/storage-up - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. univpancasila/storage-up

ActiveLibrary[File &amp; Storage](/categories/file-storage)

univpancasila/storage-up
========================

A Laravel package developed by the Internal Organization of the University of Pancasila, designed to simplify file storage management. This package provides an intuitive facade for uploading, retrieving, and managing files across organizational applications through a unified API.

v1.0.2(6mo ago)023[3 PRs](https://github.com/univpancasila/storage-up/pulls)MITPHPPHP ^8.1|^8.2|^8.3|^8.4CI passing

Since Oct 20Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/univpancasila/storage-up)[ Packagist](https://packagist.org/packages/univpancasila/storage-up)[ Docs](https://github.com/univpancasila/storageup-facade)[ GitHub Sponsors](https://github.com/:vendor_name)[ RSS](/packages/univpancasila-storage-up/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (14)Versions (7)Used By (0)

StorageUp - Laravel File Storage Package
========================================

[](#storageup---laravel-file-storage-package)

[![Latest Version on Packagist](https://camo.githubusercontent.com/72c6b2fb692db08a34d378d9d052d1fecdf243e0fe4ddac883d449edad4b8965/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f756e697670616e636173696c612f73746f726167652d75702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/univpancasila/storage-up)[![Total Downloads](https://camo.githubusercontent.com/d61e864b764dcd667f141cddf74e884bb479c8e61f5c1ee9d95d0ed331e0508f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f756e697670616e636173696c612f73746f726167652d75702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/univpancasila/storage-up)[![License](https://camo.githubusercontent.com/7a83a98b900704fc6954c0b892e02d02b4d9b330c4074f784ac895c212f4f2b6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f756e697670616e636173696c612f73746f726167652d75702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/univpancasila/storage-up)

A Laravel package developed by the Internal Organization of the University of Pancasila, designed to simplify file storage management. This package provides an intuitive facade for uploading, retrieving, and managing files across organizational applications through a unified API.

Features
--------

[](#features)

✨ **Simple &amp; Intuitive** - Clean facade interface for file operations 🔗 **Polymorphic Relations** - Attach files to any Eloquent model 📁 **Collection Management** - Organize files into named collections 🔄 **Automatic Retry** - Built-in HTTP retry mechanism (3-10 attempts, configurable) 🗄️ **Database Tracking** - Track all file metadata in your database ⚡ **Optimized Queries** - Composite indexes for fast lookups 🧪 **Fully Tested** - 54 tests with comprehensive coverage 🎯 **Type Safe** - Full type hints and PHPStan compliance ⚙️ **Configurable** - Endpoints and retry counts customizable via config

Requirements
------------

[](#requirements)

- PHP 8.1, 8.2, 8.3, or 8.4
- Laravel 9.x, 10.x, 11.x, or 12.x
- Guzzle HTTP Client 7.0+

Installation
------------

[](#installation)

### 1. Install via Composer

[](#1-install-via-composer)

```
composer require univpancasila/storage-up
```

### 2. Publish Configuration

[](#2-publish-configuration)

```
php artisan vendor:publish --tag=storageup-config
```

This creates `config/storageup.php`:

```
return [
    'api_url' => env('STORAGE_UP_API_URL', 'https://storage.univpancasila.ac.id'),

    'api_keys' => [
        'default' => env('STORAGE_UP_API_KEY'),
    ],

    'endpoints' => [
        'upload' => env('STORAGE_UP_UPLOAD_ENDPOINT', '/api/v1/storage/upload'),
        'delete' => env('STORAGE_UP_DELETE_ENDPOINT', '/api/v1/storage/delete'),
    ],

    'retry' => [
        'upload' => env('STORAGE_UP_UPLOAD_RETRY', 3),
        'delete' => env('STORAGE_UP_DELETE_RETRY', 10),
    ],

    'validation' => [
        'max_size' => env('STORAGE_UP_MAX_SIZE', 10240), // 10MB
        'allowed_mimes' => [
            'jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx',
            'xls', 'xlsx', 'txt', 'csv', 'zip', 'rar',
        ],
    ],
];
```

### 3. Publish &amp; Run Migrations

[](#3-publish--run-migrations)

```
php artisan vendor:publish --tag=storageup-migrations
php artisan migrate
```

This creates the `storage_files` table to track your uploads.

### 4. Configure Environment

[](#4-configure-environment)

Add to your `.env` file:

```
# Required
STORAGE_UP_API_URL=https://storage.univpancasila.ac.id
STORAGE_UP_API_KEY=your-api-key-here

# Optional - Customize endpoints (defaults shown)
STORAGE_UP_UPLOAD_ENDPOINT=/api/v1/storage/upload
STORAGE_UP_DELETE_ENDPOINT=/api/v1/storage/delete

# Optional - Customize retry counts (defaults shown)
STORAGE_UP_UPLOAD_RETRY=3
STORAGE_UP_DELETE_RETRY=10

# Optional - Customize validation (defaults shown)
STORAGE_UP_MAX_SIZE=10240
```

Basic Usage
-----------

[](#basic-usage)

### Upload a File

[](#upload-a-file)

```
use Univpancasila\StorageUp\Facades\StorageUp;
use App\Models\User;

$user = User::find(1);

$file = StorageUp::apiKey(config('storageup.api_keys.default'))
    ->for($user)
    ->collection('documents')
    ->upload($request->file('document'));

// Returns StorageFile model with:
// - id, original_name, filename, file_id
// - url, url_thumbnail, collection_name
// - model_type, model_id, timestamps
```

### Retrieve Files

[](#retrieve-files)

```
// Get all files from a collection
$documents = StorageUp::getFile($user, 'documents');

foreach ($documents as $doc) {
    echo $doc->original_name;
    echo $doc->url;
}

// Get only the latest file
$latestDocument = StorageUp::getFile($user, 'documents', $latest = true);
```

### Delete Files

[](#delete-files)

```
// Delete a specific file
$file = $user->storageFiles()->first();
StorageUp::deleteFile($file);

// Delete all files from a collection
StorageUp::deleteAllFiles($user, 'documents');

// Delete all files for a model
StorageUp::deleteAllFiles($user);
```

Advanced Usage
--------------

[](#advanced-usage)

### Fluent Interface

[](#fluent-interface)

Chain methods for clean, readable code:

```
$file = StorageUp::apiKey('custom-key')
    ->apiUrl('https://custom-storage.example.com')
    ->for($user)
    ->collection('profile-pictures')
    ->upload($request->file('avatar'));
```

### Custom API Configuration

[](#custom-api-configuration)

```
// Use different API keys per upload
$file = StorageUp::apiKey('admin-key')
    ->for($document)
    ->collection('confidential')
    ->upload($file);

// Use different storage endpoints
$file = StorageUp::apiUrl('https://backup.storage.com')
    ->apiKey('backup-key')
    ->for($user)
    ->upload($file);
```

### Working with Collections

[](#working-with-collections)

```
// Profile pictures
$avatar = StorageUp::apiKey(config('storageup.api_keys.default'))
    ->for($user)
    ->collection('avatars')
    ->upload($request->file('avatar'));

// Documents
$document = StorageUp::apiKey(config('storageup.api_keys.default'))
    ->for($user)
    ->collection('documents')
    ->upload($request->file('document'));

// Retrieve by collection
$avatars = StorageUp::getFile($user, 'avatars');
$documents = StorageUp::getFile($user, 'documents');
```

### Using with Any Model

[](#using-with-any-model)

StorageUp works with any Eloquent model:

```
use App\Models\Project;
use App\Models\Invoice;

// Attach to Project
$project = Project::find(1);
$file = StorageUp::apiKey(config('storageup.api_keys.default'))
    ->for($project)
    ->collection('blueprints')
    ->upload($request->file('blueprint'));

// Attach to Invoice
$invoice = Invoice::find(1);
$receipt = StorageUp::apiKey(config('storageup.api_keys.default'))
    ->for($invoice)
    ->collection('receipts')
    ->upload($request->file('receipt'));
```

Model Integration
-----------------

[](#model-integration)

### Add Relationship to Your Models

[](#add-relationship-to-your-models)

Add this to any model that needs file storage:

```
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Univpancasila\StorageUp\Models\StorageFile;

class User extends Model
{
    /**
     * Get all storage files for this user
     */
    public function storageFiles()
    {
        return $this->morphMany(StorageFile::class, 'model');
    }

    /**
     * Get files from specific collection
     */
    public function getStorageFiles(string $collection)
    {
        return $this->storageFiles()
            ->where('collection_name', $collection)
            ->get();
    }

    /**
     * Get latest file from collection
     */
    public function getLatestFile(string $collection)
    {
        return $this->storageFiles()
            ->where('collection_name', $collection)
            ->latest()
            ->first();
    }
}
```

### Using the Relationship

[](#using-the-relationship)

```
// Get all files
$allFiles = $user->storageFiles;

// Get files by collection
$documents = $user->storageFiles()
    ->where('collection_name', 'documents')
    ->get();

// Count files
$fileCount = $user->storageFiles()->count();

// Get files with specific attributes
$pdfs = $user->storageFiles()
    ->where('collection_name', 'documents')
    ->where('original_name', 'LIKE', '%.pdf')
    ->get();
```

Controller Example
------------------

[](#controller-example)

Here's a complete controller example:

```
namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Univpancasila\StorageUp\Facades\StorageUp;
use Univpancasila\StorageUp\Models\StorageFile;

class FileController extends Controller
{
    /**
     * Upload a file
     */
    public function upload(Request $request)
    {
        $request->validate([
            'file' => 'required|file|max:10240', // 10MB
            'collection' => 'required|string',
        ]);

        try {
            $user = auth()->user();

            $file = StorageUp::apiKey(config('storageup.api_keys.default'))
                ->for($user)
                ->collection($request->collection)
                ->upload($request->file('file'));

            return response()->json([
                'success' => true,
                'message' => 'File uploaded successfully',
                'file' => [
                    'id' => $file->id,
                    'name' => $file->original_name,
                    'url' => $file->url,
                    'thumbnail' => $file->url_thumbnail,
                    'collection' => $file->collection_name,
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get user files
     */
    public function index(Request $request)
    {
        $user = auth()->user();
        $collection = $request->get('collection');

        $files = $collection
            ? StorageUp::getFile($user, $collection)
            : $user->storageFiles;

        return response()->json([
            'success' => true,
            'files' => $files,
        ]);
    }

    /**
     * Delete a file
     */
    public function destroy($id)
    {
        try {
            $file = StorageFile::findOrFail($id);

            // Optional: Check ownership
            if ($file->model_id !== auth()->id()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Unauthorized',
                ], 403);
            }

            StorageUp::deleteFile($file);

            return response()->json([
                'success' => true,
                'message' => 'File deleted successfully',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Delete all files from collection
     */
    public function destroyCollection(Request $request)
    {
        $request->validate([
            'collection' => 'required|string',
        ]);

        try {
            $user = auth()->user();
            StorageUp::deleteAllFiles($user, $request->collection);

            return response()->json([
                'success' => true,
                'message' => 'All files deleted successfully',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }
}
```

API Reference
-------------

[](#api-reference)

### StorageUp Facade Methods

[](#storageup-facade-methods)

#### `apiKey(string $apiKey): self`

[](#apikeystring-apikey-self)

Set the API key for the storage service.

```
StorageUp::apiKey('your-api-key')
```

#### `apiUrl(string $url): self`

[](#apiurlstring-url-self)

Set a custom API URL.

```
StorageUp::apiUrl('https://custom.storage.com')
```

#### `collection(string $name): self`

[](#collectionstring-name-self)

Set the collection name for organizing files.

```
StorageUp::collection('documents')
```

#### `for(Model $model): self`

[](#formodel-model-self)

Set the model instance to attach files to.

```
StorageUp::for($user)
```

#### `upload(UploadedFile $file, ?string $type = null): StorageFile`

[](#uploaduploadedfile-file-string-type--null-storagefile)

Upload a file to the storage service.

```
$file = StorageUp::upload($request->file('document'));
```

**Throws:** `\Exception` if API key or model is not set.

#### `getFile(Model $model, string $collectionName, bool $latest = false)`

[](#getfilemodel-model-string-collectionname-bool-latest--false)

Retrieve files for a model and collection.

```
// Get all files
$files = StorageUp::getFile($user, 'documents');

// Get latest file only
$file = StorageUp::getFile($user, 'documents', true);
```

**Returns:** `Collection|StorageFile|null`

#### `deleteFile(StorageFile $file): ?bool`

[](#deletefilestoragefile-file-bool)

Delete a specific file from storage and database.

```
StorageUp::deleteFile($file);
```

#### `deleteAllFiles(Model $model, ?string $collectionName = null): void`

[](#deleteallfilesmodel-model-string-collectionname--null-void)

Delete all files for a model, optionally filtered by collection.

```
// Delete all files from a collection
StorageUp::deleteAllFiles($user, 'documents');

// Delete all files for a model
StorageUp::deleteAllFiles($user);
```

### StorageFile Model

[](#storagefile-model)

The `StorageFile` model has the following attributes:

```
$file->id                 // int
$file->model_type         // string (polymorphic type)
$file->model_id          // int (polymorphic id)
$file->collection_name   // string|null
$file->original_name     // string
$file->filename          // string (stored filename)
$file->file_id           // string|null (remote file ID)
$file->url               // string|null (file URL)
$file->url_thumbnail     // string|null (thumbnail URL)
$file->created_at        // Carbon
$file->updated_at        // Carbon
```

#### Model Methods

[](#model-methods)

```
// Get the parent model
$file->model(); // Returns the associated model (User, Project, etc.)

// Delete file from storage and database
$file->deleteFile(?string $apiKey = null, ?string $apiUrl = null);

// Static method to delete multiple files
StorageFile::deleteAllFiles(
    string $modelType,
    $modelId,
    ?string $collectionName = null
);
```

Blade Examples
--------------

[](#blade-examples)

### Upload Form

[](#upload-form)

```

    @csrf

            Upload File

        @error('file')
            {{ $message }}
        @enderror

            Collection

            Documents
            Images
            Videos

        Upload File

```

### Display Files

[](#display-files)

```

    @forelse($user->storageFiles as $file)

                @if($file->url_thumbnail)

                @endif

                    {{ $file->original_name }}

                        Collection: {{ $file->collection_name ?? 'Default' }}

                        Uploaded {{ $file->created_at->diffForHumans() }}

                    View

                    @csrf
                    @method('DELETE')

                        Delete

    @empty
        No files uploaded yet.
    @endforelse

```

Error Handling
--------------

[](#error-handling)

The package throws exceptions that you should catch:

```
try {
    $file = StorageUp::apiKey(config('storageup.api_keys.default'))
        ->for($user)
        ->collection('documents')
        ->upload($request->file('document'));

} catch (\Exception $e) {
    // Handle errors
    if (str_contains($e->getMessage(), 'API key not set')) {
        // API key configuration error
    } elseif (str_contains($e->getMessage(), 'Model not set')) {
        // Model not provided
    } elseif (str_contains($e->getMessage(), 'Failed to upload')) {
        // Upload failed (network, API error, etc.)
    } else {
        // Other errors
    }

    Log::error('File upload failed', [
        'error' => $e->getMessage(),
        'user_id' => $user->id ?? null,
    ]);

    throw $e;
}
```

Testing
-------

[](#testing)

The package includes comprehensive tests:

```
# Run all tests
composer test

# Run specific test suites
./vendor/bin/pest tests/Unit
./vendor/bin/pest tests/Feature
./vendor/bin/pest tests/Integration

# Run with coverage
composer test-coverage

# Run static analysis
composer analyse

# Fix code style
composer format
```

### Writing Tests for Your Application

[](#writing-tests-for-your-application)

```
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Http;
use Univpancasila\StorageUp\Facades\StorageUp;

test('user can upload document', function () {
    Http::fake([
        '*/api/v1/storage/upload' => Http::response([
            'status' => 'success',
            'data' => [
                'fileName' => 'test-document.pdf',
                'fileId' => 'file-123',
                'link' => 'https://storage.example.com/test-document.pdf',
            ],
        ], 200),
    ]);

    $user = User::factory()->create();
    $file = UploadedFile::fake()->create('document.pdf', 1024);

    $response = $this->actingAs($user)
        ->post('/upload', [
            'file' => $file,
            'collection' => 'documents',
        ]);

    $response->assertOk();

    $this->assertDatabaseHas('storage_files', [
        'model_type' => User::class,
        'model_id' => $user->id,
        'collection_name' => 'documents',
        'original_name' => 'document.pdf',
    ]);
});
```

Configuration
-------------

[](#configuration)

### Multiple API Keys

[](#multiple-api-keys)

You can configure multiple API keys in `config/storageup.php`:

```
'api_keys' => [
    'default' => env('STORAGE_UP_API_KEY'),
    'admin' => env('STORAGE_UP_ADMIN_KEY'),
    'backup' => env('STORAGE_UP_BACKUP_KEY'),
],
```

Usage:

```
// Use default key
StorageUp::apiKey(config('storageup.api_keys.default'))

// Use admin key
StorageUp::apiKey(config('storageup.api_keys.admin'))

// Use backup key
StorageUp::apiKey(config('storageup.api_keys.backup'))
```

### API Endpoints

[](#api-endpoints)

Customize API endpoints in `config/storageup.php`:

```
'endpoints' => [
    'upload' => env('STORAGE_UP_UPLOAD_ENDPOINT', '/api/v1/storage/upload'),
    'delete' => env('STORAGE_UP_DELETE_ENDPOINT', '/api/v1/storage/delete'),
],
```

You can override these in your `.env` file:

```
STORAGE_UP_UPLOAD_ENDPOINT=/api/v1/storage/upload
STORAGE_UP_DELETE_ENDPOINT=/api/v1/storage/delete
```

This is useful when:

- Using a different API version
- Testing with a staging endpoint
- Implementing custom routing on the storage server

### HTTP Retry Configuration

[](#http-retry-configuration)

Configure retry attempts for each operation in `config/storageup.php`:

```
'retry' => [
    'upload' => env('STORAGE_UP_UPLOAD_RETRY', 3),
    'delete' => env('STORAGE_UP_DELETE_RETRY', 10),
],
```

**Why different retry counts?**

- **Upload (3 retries)**: Files are typically large, so fewer retries prevent long wait times
- **Delete (10 retries)**: Lightweight operation, more retries ensure reliability

Override in `.env`:

```
STORAGE_UP_UPLOAD_RETRY=5
STORAGE_UP_DELETE_RETRY=15
```

### Validation Rules

[](#validation-rules)

Configure file validation in `config/storageup.php`:

```
'validation' => [
    'max_size' => env('STORAGE_UP_MAX_SIZE', 10240), // kilobytes
    'allowed_mimes' => [
        'jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx',
        'xls', 'xlsx', 'txt', 'csv', 'zip', 'rar',
    ],
],
```

Apply in your validation:

```
$request->validate([
    'file' => [
        'required',
        'file',
        'max:' . config('storageup.validation.max_size'),
        'mimes:' . implode(',', config('storageup.validation.allowed_mimes')),
    ],
]);
```

Performance Tips
----------------

[](#performance-tips)

### Database Optimization

[](#database-optimization)

The package includes optimized indexes. To check:

```
-- Check indexes on storage_files table
SHOW INDEX FROM storage_files;
```

You should see:

- Composite index on `model_type`, `model_id`, `collection_name`
- Index on `file_id`

### Eager Loading

[](#eager-loading)

When retrieving multiple models with files:

```
// ❌ Bad - N+1 query problem
$users = User::all();
foreach ($users as $user) {
    $files = $user->storageFiles; // Separate query per user
}

// ✅ Good - Single query with eager loading
$users = User::with('storageFiles')->get();
foreach ($users as $user) {
    $files = $user->storageFiles; // Already loaded
}

// ✅ Even better - Load specific collection
$users = User::with(['storageFiles' => function ($query) {
    $query->where('collection_name', 'documents');
}])->get();
```

### Caching File URLs

[](#caching-file-urls)

Cache frequently accessed file URLs:

```
use Illuminate\Support\Facades\Cache;

$avatarUrl = Cache::remember(
    "user.{$user->id}.avatar",
    now()->addHours(24),
    fn() => StorageUp::getFile($user, 'avatars', true)?->url
);
```

Troubleshooting
---------------

[](#troubleshooting)

### Issue: "API key not set"

[](#issue-api-key-not-set)

**Solution:** Make sure to call `apiKey()` before `upload()`:

```
StorageUp::apiKey(config('storageup.api_keys.default'))
    ->for($user)
    ->upload($file);
```

### Issue: "Model not set"

[](#issue-model-not-set)

**Solution:** Make sure to call `for()` before `upload()`:

```
StorageUp::apiKey(config('storageup.api_keys.default'))
    ->for($user) // Required
    ->upload($file);
```

### Issue: "Failed to upload file to storage service"

[](#issue-failed-to-upload-file-to-storage-service)

**Solutions:**

1. Check API key is valid
2. Verify API URL is correct and accessible
3. Check network connectivity
4. Review file size limits
5. Check API server logs

### Issue: Files not appearing in database

[](#issue-files-not-appearing-in-database)

**Solution:** Run migrations:

```
php artisan migrate

# Or republish and migrate
php artisan vendor:publish --tag=storageup-migrations --force
php artisan migrate:fresh
```

### Issue: Facade not found

[](#issue-facade-not-found)

**Solutions:**

```
# Clear caches
php artisan config:clear
php artisan cache:clear
php artisan clear-compiled

# Rebuild autoload
composer dump-autoload

# Ensure service provider is registered
php artisan package:discover
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

### Development Setup

[](#development-setup)

```
# Clone repository
git clone https://github.com/univpancasila/storageup-facade.git
cd storageup-facade

# Install dependencies
composer install

# Run tests
composer test

# Check code style
composer analyse

# Fix code style
composer format
```

Security
--------

[](#security)

If you discover any security-related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Abdan Syakuro](https://github.com/abdansyakuro) - Developer
- [University of Pancasila](https://univpancasila.ac.id) - Organization
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

---

**Made with ❤️ by Internal Organization of University of Pancasila**

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance80

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

3

Last Release

205d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3ba5ee30371db044cf7d4b7c58a4b28357686c16a2c2966f946ff171671697d0?d=identicon)[univpancasila](/maintainers/univpancasila)

---

Top Contributors

[![univpancasila](https://avatars.githubusercontent.com/u/145424644?v=4)](https://github.com/univpancasila "univpancasila (8 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (7 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (5 commits)")[![developerabdan](https://avatars.githubusercontent.com/u/42459820?v=4)](https://github.com/developerabdan "developerabdan (4 commits)")

---

Tags

laravelunivpancasilastorage-up

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/univpancasila-storage-up/health.svg)

```
[![Health](https://phpackages.com/badges/univpancasila-storage-up/health.svg)](https://phpackages.com/packages/univpancasila-storage-up)
```

###  Alternatives

[spatie/laravel-health

Monitor the health of a Laravel application

85810.0M83](/packages/spatie-laravel-health)[spatie/livewire-filepond

Upload files using Filepond in Livewire components

306452.7k3](/packages/spatie-livewire-filepond)[elegantly/laravel-invoices

Store invoices safely in your Laravel application

23131.8k](/packages/elegantly-laravel-invoices)[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

24149.7k](/packages/vormkracht10-laravel-mails)[sunchayn/nimbus

A Laravel package providing an in-browser API client with automatic schema generation, live validation, and built-in authentication with a touch of Laravel-tailored magic for effortless API testing.

29428.0k](/packages/sunchayn-nimbus)[muhammadhuzaifa/telescope-guzzle-watcher

Telescope Guzzle Watcher provide a custom watcher for intercepting http requests made via guzzlehttp/guzzle php library. The package uses the on\_stats request option for extracting the request/response data. The watcher intercept and log the request into the Laravel Telescope HTTP Client Watcher.

98239.8k1](/packages/muhammadhuzaifa-telescope-guzzle-watcher)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
