Laravel resource links two years later

Today we're abandoning spatie/laravel-resource-links. This was the first PHP package I've build and I'm still kinda proud of it but sometimes it is better to say goodbye.

The package provided some helper functions you could use within your Laravel Resources to add urls to parts of your application. For example, let's say we have a UserController and a UserResource for a User model:

class UserResource extends JsonResource
{
    use HasLinks, HasMeta;
    
    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'links' => $this->links(UsersController::class),
        ];
    }

    public static function meta()
    {
        return [
            'links' => self::collectionLinks(UsersController::class),
        ];
    }
}

In a response this would become the following Json:

{
   "data":[
      {
         "id":1,
         "name": "Ruben Van Assche",
         "email": "ruben@spatie.be"
         "links": {
            "show": "https://laravel.app/users/1",
            "edit": "https://laravel.app/users/1/edit",
            "update": "https://laravel.app/users/1",
            "delete": "https://laravel.app/users/1"
         }
      }
   ],
   "meta": {
      "links": {
         "index": "https://laravel.app/users",
         "create": "https://laravel.app/users/create",
         "store":  "https://laravel.app/users"
      }
   }
}

It was actually a url generator for lazy developers.

Why abandoning the package?

Allthoug the package still works, and I'll guess as long as Laravel doesn't change too much about the routing systsem it will still work for quite a while we decided to stop the development.

Originally this package was built for one project, and it is still being used there. But since then we've created many (much bigger) projects then that one project and tought we could use this package. But we didn't.

The idea initially sounded great, never write links in resources again. But it is actually not that much work to write links, if we rewrite the above resource for example:

class UserResource extends JsonResource
{
    use HasLinks, HasMeta;

    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'links' => [
                "show" => action([UsersController::class, 'show'], $this),
                "edit" => action([UsersController::class, 'edit'], $this),
                "update" => action([UsersController::class, 'update'], $this),
                "delete" => action([UsersController::class, 'delete'], $this),
            ],
        ];
    }

    public static function meta()
    {
        return [
            'links' => [
                "index" => action([UsersController::class, 'index']),
                "create" => action([UsersController::class, 'create']),
                "store" => action([UsersController::class, 'store']),
            ]
        ];
    }
}

That's not so bad, it's a bit more code but a lot more readable. Adding or removing certain links from a resource is now super easy. Do you want to add an array with some extra endpoints within the links property? Not a problem! Do you want use other names for the link properties? Change them! Do you want to add an action to another controller? Do it!

Although the package supported all these features, they weren't always that easy to use. Almost always when adding links you had to check the docs if you wanted to do something little more complicated than just adding a link to a controller.

That brings us to the next reason for abandonment, magic! Automatically generated links sounded great in the beginning but they are a big black magic box you don't want to open. Most of the time the package worked as expected. But there were cases where it didn't and debugging those cases was hard. Especially those cases where you had resources within resources, the horrors!

The package replaced some parts of the Laravel routing system so it could plug into it and also did some crazy stuff with the Laravel Resources, they actually weren't built for this kind of stuff.

I haven't touched the code for two years and I actually have no idea what it does and how it works. There is a class ParameterResolver that's a 130 lines, it tries to find parameters for constructing the links and I'm really scared of it. That's not a good sign.

My first though was to write a second version, a more light version of the package. But that would still require a lot of crazy code to interface with Laravel. Why would we?

Conclusion

That's it, farewell laravel-resource-links, you were the first package I've ever made, since then I've learned so much about package development, but your time has come.

If you don't want to manually change all your links within your application take a look at Ziggy it works a bit different then laravel-resource-links but also has the ability to automatically generate links.