PHPackages                             yanmarques/lincable - 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. [Database &amp; ORM](/categories/database)
4. /
5. yanmarques/lincable

ActivePackage[Database &amp; ORM](/categories/database)

yanmarques/lincable
===================

Storage link generator for laravel Eloquent

v1.0.2(7y ago)481MITPHP &gt;=7.1

Since Jul 1Compare

[ Source](https://github.com/yanmarques/lincable)[ Packagist](https://packagist.org/packages/yanmarques/lincable)[ RSS](/packages/yanmarques-lincable/feed)WikiDiscussions Synced 2w ago

READMEChangelog (10)Dependencies (11)Versions (17)Used By (0)

Lincable
========

[](#lincable)

[![Build Status](https://camo.githubusercontent.com/7b69a30c0066c892661f701cf270f1e964ca99c259d619b6eb1cb9f9d93078d0/68747470733a2f2f7472617669732d63692e6f72672f79616e6d6172717565732f6c696e6361626c652e7376673f6272616e63683d646576)](https://travis-ci.org/yanmarques/lincable)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/460cc310eadf55ea491cb2891791d80299810a82fd9a9d15457b6228bc4b7765/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f79616e6d6172717565732f6c696e6361626c652f6261646765732f7175616c6974792d73636f72652e706e673f623d646576)](https://scrutinizer-ci.com/g/yanmarques/lincable/?branch=dev)

Link the Eloquent model to an uploaded file, store the file on storage and then save the url on model. ☁️

Table Of Contents
=================

[](#table-of-contents)

- [Basic Usage](#basic-usage)
- [Getting Started](#getting-started)
    - [Installing](#installing)
    - [Register the Service Provider](#register-the-service-provider)
    - [Publish Configuration](#publish-configuration)
    - [Configuring The Model](#configuring-the-model)
    - [FileRequest](#filerequest)
    - [Parsers and Formatters](#parsers-and-formatters)
    - [UrlGenerator](#urlgenerator)
- [Testing](#testing)
- [Lincese](#license)

Why this?
=========

[](#why-this)

The lincable package handle the file upload, store the file on some disk storage and link the model with the uploaded file. The whole upload process until getting the file saved and linked with the model, is well configured to provide you assistance at all steps. The link generated for the model can have dynamic parameters to be implicitly injected with the model attributes, or execute any custom logic.

[![Database lik image](https://camo.githubusercontent.com/5ae7cfe2f0d52b5ed8be4994d48cd08acc6f22e93b3d81440a8026d082364b4b/68747470733a2f2f7777772e64657369676e626f6d62732e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031362f30342f64617461626173652d636f6e6e656374696f6e2d31303234783432352e6a7067)](https://camo.githubusercontent.com/5ae7cfe2f0d52b5ed8be4994d48cd08acc6f22e93b3d81440a8026d082364b4b/68747470733a2f2f7777772e64657369676e626f6d62732e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031362f30342f64617461626173652d636f6e6e656374696f6e2d31303234783432352e6a7067)

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

[](#basic-usage)

When working with file uploads, generally we expect some data types on upload, or we need to move the temporary file created by PHP to a correct location. Controller's action should not have file manipulation logic, but putting these logic on controller make the it becomes duplicate code, once this kind of manipulation is generally the same. `FileRequest` class solves this problem, removing the upload logic from controller. Sure, the class also carries the rules to validate the file and execute an event method before saving the file. Using the file request as parameter of the action ensures the data type been uploaded.

Here is the action to execute the upload.

```
/**
 * Upload an image to application.
 *
 * @param  ImageFileRequest $image
 * @return Response
 */
public function upload(ImageFileRequest $image)
{
    // The ImageFileRequest contains the current request.
    $request = $image->getRequest();

    // Create the image model on database with request attributes.
    $image = \App\Image::create($request->all());

    // The model uses the lincable trait, which has the link method
    // that store the file and generate a url for the model.
    $image->link($image);

    $image->preview; // https://your-cloud-storage.com/media/foo/123/bar/321/e1wPJQmQpFPOaQ238fglQHnrxzv2uK8joPyozv9i.jpg
}
```

Getting Started
===============

[](#getting-started)

Installing
----------

[](#installing)

We must add this package as dependency for your project, adding to your `composer.json` file.

```
{
    "require-dev": {
        "yanmarques/lincable": "^0.11.0"
    }
}
```

Or install using [composer](https://getcomposer.org/):

```
$ composer require yanmarques/lincable
```

Or using git:

```
$ git clone git@github.com:yanmarques/lincable.git
```

Or you can just download the binaries [releases](https://github.com/yanmarques/lincable/releases).

Register The Service Provider
-----------------------------

[](#register-the-service-provider)

You need to register the package with laravel, adding the service provider on the application providers. At the `config/app.php` add this to your providers:

```
return [
    'providers' => [
        ...
        /*
         * Package Service Providers...
         */
        Lincable\Providers\MediaManagerServiceProvider::class,
    ]
]
```

Publish Configuration
---------------------

[](#publish-configuration)

Basically, you must to configurate the lincable file to get everything running cool. This configuraton file will be available at `config/lincable.php` after you have published the service container assets with:

```
$ php artisan vendor:publish --provider="Lincable\Providers\MediaManagerServiceProvider"
```

Now we have registered the package on your environment, and we need to start configuring how lincable should work. The package is very flexible given you control to decide how to use it, there is no a only way.

Configuring The Model
---------------------

[](#configuring-the-model)

The eloquent model will be responsable to link the file. The link will be generated based on the lincable file configuration, by the [url generator](#urlgenerator). On model we just need to add the [lincable trait](#lincable-trait) to support linking the model with a file. Suppose we have an image model which has an `id` and `user_id` attributes, both uuid type.

```
use Lincable\Eloquent\Trait\Lincable;

class Image extends Model
{
    use Lincable;

    protected $fillable = ['user_id'];
}
```

Once we have our model, we need to define the url generated for the model. We must set the urls on `config/lincable.php`. Urls is the list with all model urls configuration. Each model has an url, and this one, by default has dynamic parameters to be injected with the model attributes, see [parsers and formatters](#parsers-and-formatters) for more details of how to use default dynamic parameters. For example, we want to save the file in an url that contains the `user_id` and the model `id`, something like that this path: `users/user-id-here/ìmages/id-here/`. We can inject model attributes on url using the url dynamic parameters.

Here the file `config/lincable.php` configuration.

```
return [
    ...
   'urls' => [
        \App\Image::class => 'users/:user_id/images/:id'
    ]
];
```

Ok, now we create the controller to handle the upload. Laravel uses the containter dependency injection to resolve classes, methods, closures, etc..., the controller action registered on route has this definition as well. As seen before at [basic usage](#basic-usage), the controller should receive the file request as argument, this is nice because the file request must be booted with the current request to work, and when the container resolves a file request, it boots the object with the request. The code at basic usage ensures the file type, because as explained before, the file request as service must be booted with the current request, and this process is necessary to validate the file with the rules. Once the file is not valid, we do not even execute the action code.

The `ImageFileRequest` extends from the `FileRequest` abstract class that actually handles the validation and configuration on file. When file request is booted with the curren request stack, we try to load the file uploaded from class name, in this case the file parameter would be `image`. The only abstract method to implement is the `rules`, that returns the validation rules for the uploaded file, see laravel [validations](https://laravel.com/docs/5.6/validation#rule-mimes) for more details.

FileRequest
-----------

[](#filerequest)

The controller to upload the files will handle the file upload and storing it on cloud and saving the link on the database. The file request will be a file manager defining how the file upload will be performed and what kind of data type is expected for the controller upload. This enforces the data type and rules for the file upload, making generic file requests that can work with more other controllers that receives same file types.

```
/**
 * Upload a image to application.
 *
 * @param  \App\FileRequests\ImageFileRequest $image
 * @return response
 */
public function upload(ImageFileRequest $image)
```

On the `App\FileRequests\ImageFileRequest` class we define rules for images upload on the application, and what to do with the file before effectively storing it on disk storage. For example, we want to resize the image upload before storing it. We are calling `Image` facade from [intervention](http://image.intervention.io) image manipulation.

```
use Image;
use Lincable\Http\FileRequest;

class ImageFileRequest extends FileRequest
{
    protected function rules()
    {
        return 'required:jpg,png';
    }

    protected function beforeSend($file)
    {
        // The do not need to return a file, because the image has
        // been saved an the changes will reflect.
        Image::make($file)->resize(600, 400)->save();
    }
}
```

Parsers and Formatters
----------------------

[](#parsers-and-formatters)

To allow dynamic parameters on the url we must provide a Parser class to define how the parameters will be presented on the url. There is no only way, you should create your own. By default we provide the `\Lincable\Parsers\ColonParser` which is a parser implementation for parameters beginning with a colon, very simple. Parsers just extract dynamic parameters from parts of the url, but the formatter that really execute the parameter logic. By default we add some formatters for the colon parser:

- `year`: Returns the current year.
- `month`: Returns the current month.
- `day`: Returns the current day.
- `random`: Returns a random string of 32 length.
- `timestamps`: Returns the hashed current UNIX timestamp.

The parser allows you to pass parameters for the formatter using the regex pattern to split the matches. You can also pass an anonymous function to the parser with a class dependency, and the container will resolve the class instance.

Suppose we want to store a file in diferente locations depending on a token or id on the request. We can create a formatter to execute this task with the request.

```
$colonParser->addFormatter(function (Request $request) {
    if ($request->user()->isBoss()) {
        return 'boss-location';
    }

    return 'baz';
}, 'customLocation');

$url = 'foo/:customLocation';

// Is user on request is the boss.
'foo/boss-location/dqiojqwdij.zip'

// The user on request is not the boss.
'foo/baz/dqiojqwdij.zip';
```

You can also configure a formatter class on lincable configuration. First we create the formatter, for example, pretend we want to create the link based on an api service. We need an especialized class to solve this problem. Let's create a dummy not functional class that retrieves and identifier for the current authenticated user on request from a client api.

```
namespace App\Formatters;

...

class GetApiIdFormatter
{
    /**
     * Attributes initialized here.
     */

    public function __construct(ApiClient $api, Config $params)
    {
        $this->api = $api;
        $this->setConfig($config);

        // More function tasks.
    }

    /**
     * More complex methods here.
     */

    public function format(Request $request)
    {
        return $this->getIdForUser($request->user());
    }
}
```

Now we add the formatter class to lincable configuration. Now we add the formatter to the default package parser, the `ColonParser`.

```
return [
    ...

    default_parsers => [
         \Lincable\Parsers\ColonParser::class => [
            \Lincable\Formatters\YearFormatter::class,
            \Lincable\Formatters\DayFormatter::class,
            \Lincable\Formatters\MonthFormatter::class,
            \Lincable\Formatters\RandomFormatter::class,
            \Lincable\Formatters\TimestampsFormatter::class,

            /**
             * Here we add the formatter
             */
             \App\Formatters\GetApiIdFormatter::class
        ]
    ]
];
```

UrlGenerator
------------

[](#urlgenerator)

The url generator compiles a given url for the model instance, based on url configuration.

```
$file->toArray(); // ['id' => 123, 'foo_id' => 321,'preview' => null]

$urlConf = new UrlConf; // Create the model url configuration.

$urlConf->push(File::class, ':year/:id/:month/:foo_id');

$generator = new UrlGenerator($urlCompiler, $parsers, $urlConf);

$preview = $generator->forModel($file)->generate(); // Generate the url for the model from configuration.

$preview; // 'https://your-disk-storage.com/2018/123/07/321/HJSxDckZZcMbc8AiWxzlg1Jx2gBVYO6kBqhna6Td.zip'
```

Testing
=======

[](#testing)

We make the world a better place with tests ![:octocat:](https://github.githubassets.com/images/icons/emoji/octocat.png ":octocat:")

```
$ vendor/bin/phpunit
```

License
=======

[](#license)

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.

###  Health Score

30

—

LowBetter than 62% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity66

Established project with proven stability

 Bus Factor1

Top contributor holds 99.6% of commits — single point of failure

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

Recently: every ~38 days

Total

13

Last Release

2757d ago

Major Versions

v0.11 → v1.0.02018-07-14

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/28604565?v=4)[Yan Marques](/maintainers/yanmarques)[@yanmarques](https://github.com/yanmarques)

---

Top Contributors

[![yanmarques](https://avatars.githubusercontent.com/u/28604565?v=4)](https://github.com/yanmarques "yanmarques (280 commits)")[![jacsonFJ](https://avatars.githubusercontent.com/u/30412353?v=4)](https://github.com/jacsonFJ "jacsonFJ (1 commits)")

---

Tags

laravellinkeloquentstorage

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/yanmarques-lincable/health.svg)

```
[![Health](https://phpackages.com/badges/yanmarques-lincable/health.svg)](https://phpackages.com/packages/yanmarques-lincable)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k51.0M7.7k](/packages/larastan-larastan)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77018.2M122](/packages/laravel-mcp)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9772.3M122](/packages/roots-acorn)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

815320.5k3](/packages/defstudio-telegraph)[api-platform/laravel

API Platform support for Laravel

59156.3k11](/packages/api-platform-laravel)

PHPackages © 2026

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