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.1.0(2mo ago)033MITPHPPHP ^8.1|^8.2|^8.3|^8.4CI passing

Since Oct 20Pushed 2mo 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 today

READMEChangelog (1)Dependencies (28)Versions (10)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 by the Internal Organization of the University of Pancasila. Provides a clean facade for uploading, retrieving, and deleting files via a unified storage API.

Features
--------

[](#features)

- Simple facade interface with fluent method chaining
- Polymorphic relations — attach files to any Eloquent model
- Named collections for organizing files
- Automatic HTTP retry (configurable)
- Database tracking of all file metadata
- Composite indexes for fast lookups
- 54 tests with comprehensive coverage

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

[](#requirements)

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

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

[](#installation)

**1. Install via Composer**

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

**2. Publish configuration**

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

**3. Publish and run migrations**

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

**4. Configure environment**

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

# Optional
STORAGE_UP_UPLOAD_ENDPOINT=/api/v1/storage/upload
STORAGE_UP_DELETE_ENDPOINT=/api/v1/storage/delete
STORAGE_UP_UPLOAD_RETRY=3
STORAGE_UP_DELETE_RETRY=10
STORAGE_UP_MAX_SIZE=10240
```

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

[](#basic-usage)

### Upload a File

[](#upload-a-file)

```
use Univpancasila\StorageUp\Facades\StorageUp;

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

// $file is a StorageFile model:
// id, original_name, filename, file_id, url, url_thumbnail,
// collection_name, model_type, model_id, timestamps
```

### Retrieve Files

[](#retrieve-files)

```
// All files in a collection
$documents = StorageUp::getFile($user, 'documents');

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

### Delete Files

[](#delete-files)

```
// Delete a specific file
StorageUp::deleteFile($file);

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

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

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

[](#advanced-usage)

### Custom API Configuration

[](#custom-api-configuration)

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

### Any Eloquent Model

[](#any-eloquent-model)

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

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

[](#model-integration)

Add a relationship to any model that needs file storage:

```
use Univpancasila\StorageUp\Models\StorageFile;

class User extends Model
{
    public function storageFiles()
    {
        return $this->morphMany(StorageFile::class, 'model');
    }
}
```

Usage:

```
// Eager load to avoid N+1
$users = User::with('storageFiles')->get();

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

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

[](#controller-example)

```
use Univpancasila\StorageUp\Facades\StorageUp;
use Univpancasila\StorageUp\Models\StorageFile;

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

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

        return response()->json([
            'id' => $file->id,
            'name' => $file->original_name,
            'url' => $file->url,
            'thumbnail' => $file->url_thumbnail,
        ]);
    }

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

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

        return response()->json($files);
    }

    public function destroy($id)
    {
        $file = StorageFile::findOrFail($id);

        abort_if($file->model_id !== auth()->id(), 403);

        StorageUp::deleteFile($file);

        return response()->json(['message' => 'File deleted']);
    }
}
```

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

[](#api-reference)

### Facade Methods

[](#facade-methods)

MethodDescription`apiKey(string $apiKey): self`Set API key`apiUrl(string $url): self`Set custom API URL`collection(string $name): self`Set collection name`for(Model $model): self`Bind to an Eloquent model`upload(UploadedFile $file, ?string $type = null): StorageFile`Upload file`getFile(Model $model, string $collectionName, bool $latest = false)`Retrieve files`deleteFile(StorageFile $file): ?bool`Delete a file`deleteAllFiles(Model $model, ?string $collectionName = null): void`Bulk delete### StorageFile Attributes

[](#storagefile-attributes)

```
$file->id
$file->model_type       // polymorphic type
$file->model_id         // polymorphic id
$file->collection_name
$file->original_name
$file->filename
$file->file_id          // remote storage ID
$file->url
$file->url_thumbnail
$file->created_at
$file->updated_at
```

### StorageFile Methods

[](#storagefile-methods)

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

// Static bulk delete
StorageFile::deleteAllFiles(string $modelType, $modelId, ?string $collectionName = null): void;
```

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

[](#configuration)

`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), // KB
        'allowed_mimes' => ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx',
                            'xls', 'xlsx', 'txt', 'csv', 'zip', 'rar'],
    ],
];
```

Use multiple API keys:

```
StorageUp::apiKey(config('storageup.api_keys.admin'))->...
```

Apply validation in controllers:

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

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

[](#error-handling)

```
try {
    $file = StorageUp::apiKey(config('storageup.api_keys.default'))
        ->for($user)
        ->collection('documents')
        ->upload($request->file('document'));
} catch (\Exception $e) {
    Log::error('File upload failed', ['error' => $e->getMessage()]);
    throw $e;
}
```

Possible exception messages:

- `"API key not set. Use apiKey() method first."` — call `apiKey()` before `upload()`
- `"Model not set. Use for() method first."` — call `for()` before `upload()`
- `"Failed to upload file to storage service."` — network or API error

Testing
-------

[](#testing)

```
composer test           # Run all tests
composer test-coverage  # With coverage
composer analyse        # PHPStan static analysis
composer format         # Pint code style
```

Mocking in your application tests:

```
use Illuminate\Support\Facades\Http;

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

Blade Example
-------------

[](#blade-example)

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

        @if($file->url_thumbnail)

        @endif

        {{ $file->original_name }}
        {{ $file->collection_name ?? 'Default' }}
        View

            @csrf @method('DELETE')
            Delete

@empty
    No files uploaded yet.
@endforelse
```

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

[](#performance-tips)

Cache frequently accessed URLs:

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

Eager load relationships:

```
$users = User::with('storageFiles')->get();

// Or scoped to a collection
$users = User::with(['storageFiles' => fn($q) =>
    $q->where('collection_name', 'documents')
])->get();
```

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

[](#troubleshooting)

**Facade not found**

```
php artisan config:clear && php artisan package:discover && composer dump-autoload
```

**Files not in database**

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

**Upload fails** — verify API key, URL reachability, and file size against `STORAGE_UP_MAX_SIZE`.

Changelog
---------

[](#changelog)

See [CHANGELOG](CHANGELOG.md) for recent changes.

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

[](#contributing)

Pull requests are welcome. For development setup:

```
git clone https://github.com/univpancasila/storageup-facade.git
cd storageup-facade
composer install
composer test
```

Security
--------

[](#security)

Report security issues to  instead of the issue tracker.

Credits
-------

[](#credits)

- [Abdan Syakuro](https://github.com/developerabdan)
- [University of Pancasila](https://univpancasila.ac.id)

License
-------

[](#license)

MIT — see [LICENSE](LICENSE.md).

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance88

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity59

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 ~65 days

Total

4

Last Release

62d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/145424644?v=4)[univpancasila](/maintainers/univpancasila)[@univpancasila](https://github.com/univpancasila)

---

Top Contributors

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

87512.0M167](/packages/spatie-laravel-health)[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.8M47](/packages/spatie-laravel-pdf)[nativephp/mobile

NativePHP for Mobile

1.1k75.1k96](/packages/nativephp-mobile)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.0k](/packages/simplestats-io-laravel-client)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.6k](/packages/rawilk-profile-filament-plugin)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

44855.7k](/packages/harris21-laravel-fuse)

PHPackages © 2026

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