Skip to content

Package development · Open source

Laralink

Work on a Composer package inside the Laravel app that uses it, then switch back to the Packagist release.

Laravel 12 and 13 PHP 8.3+ v2.0.0 Free · MIT
Laralink: Work on a Composer package inside the Laravel app that uses it, then switch back to the Packagist release.

What it solves

To develop a package inside the app that uses it, you add a path repository to composer.json, require the package at @dev, and later undo both and restore the constraint you had.

Done by hand, a failed install leaves composer.json half edited and the old constraint is easy to lose.

laralink:dev links a package from a local folder or a Git repository through a symlinked Composer path repository, so every edit shows up in the app immediately. laralink:publish puts back the constraint the package had before and installs the released version.

  • Link from a local folder (symlinked, or copied with --copy) or any Git URL and branch
  • The path repository goes first in composer.json, so it wins over Packagist
  • Checks the package's PHP and Laravel constraints against your app before changing anything
  • Restores composer.json and removes the new link or clone if Composer cannot install the package
  • laralink:publish restores the exact constraint the package had before it was linked
  • Never deletes a symlinked source folder, or a clone with uncommitted changes unless you back it up or force it
A terminal running php artisan laralink:dev --source=~/code/greeter: PHP and Laravel constraint checks both OK, a symlink from ./packages/acme/greeter to ~/code/greeter, and acme/greeter installed from ./packages; then laralink:list --filter=local shows a table with two linked packages.
A terminal running php artisan laralink:dev --source=~/code/greeter: PHP and Laravel constraint checks both OK, a symlink from ./packages/acme/greeter to ~/code/greeter, and acme/greeter installed from ./packages; then laralink:list --filter=local shows a table with two linked packages.

Install

Requires PHP 8.3+ and Laravel 12 and 13.

composer require amjadiqbal/laralink --dev

Usage

php artisan laralink:dev --source=~/code/my-package   # link a folder on your machine
php artisan laralink:dev vendor/package --branch=fix   # or clone a branch from GitHub
php artisan laralink:list                              # what is linked, what is installed
php artisan laralink:publish vendor/package            # back to the Packagist release

Setup

The service provider is discovered automatically and there is nothing to publish or configure. You need Composer 2 and Git on your PATH, and macOS or Linux for symlinks (on Windows use --copy). Add /packages to your app's .gitignore if you don't want linked packages committed.

What happens, in order

  1. 1 The package's composer.json is read (after cloning, for Git sources) and its name decides where it goes: ./packages/vendor/package.
  2. 2 Its php and Laravel constraints are checked against your app.
  3. 3 The folder is symlinked, copied or cloned into ./packages/vendor/package.
  4. 4 A path repository with "symlink": true is added first in your composer.json.
  5. 5 composer require vendor/package:@dev --with-all-dependencies runs, with --dev if the package was in require-dev.

See what is linked, and switch back

laralink:list shows each package's constraint, the version installed according to composer.lock, and a status: Linked, Local files, not linked, Linked, not required, or Remote. laralink:publish removes the path repository and installs the constraint the package had before it was linked, or the latest release. If no released version can be installed, composer.json is restored and the package stays linked.

php artisan laralink:list --filter=local
php artisan laralink:list --json

php artisan laralink:publish vendor/package --delete --backup

New in 2.0

1.x was never on Packagist. In 2.0 the three commands were rebuilt.

  • --source, --branch, --copy, --skip-version-check and --force on laralink:dev.
  • The PHP and Laravel compatibility check.
  • laralink:list --json and --filter.
  • laralink:publish --backup and --force, and restoring the previous constraint.
  • Undoing its own changes when Composer fails.
  • Requires PHP 8.3+ and Laravel 12 or 13.

Hire me

Need this built into your app, or something custom?

I wrote Laralink. I can wire it into your Laravel app, extend it for your case, or build the feature around it. Tell me what you need and you'll get a plan and a quote, free.

Support

Found a bug or want a feature? Open an issue on GitHub. For help adding it to your own project, use the quote form above.

More Laravel packages

All packages
Laravel Driver.js: Build Driver.js product tours in PHP and render them with one Blade component.

Laravel Driver.js

Build Driver.js product tours in PHP and render them with one Blade component.

Laravel Sonner: Sonner toast notifications for Laravel, sent from PHP and shown without React.

Laravel Sonner

Sonner toast notifications for Laravel, sent from PHP and shown without React.

Laravel Ninja Keys: A Cmd+K / Ctrl+K command palette for Laravel, with the actions defined in PHP.

Laravel Ninja Keys

A Cmd+K / Ctrl+K command palette for Laravel, with the actions defined in PHP.

Laravel SweetAlert2: SweetAlert2 popups, toasts and confirm dialogs from Laravel controllers, Livewire and Alpine.

Laravel SweetAlert2

SweetAlert2 popups, toasts and confirm dialogs from Laravel controllers, Livewire and Alpine.

Laravel Grid.js: Turn any Eloquent query into a searchable, sortable, paginated Grid.js data table with one fluent PHP call.

Laravel Grid.js

Turn any Eloquent query into a searchable, sortable, paginated Grid.js data table with one fluent PHP call.

Refresher: A drop-in replacement for Laravel's RefreshDatabase that restores a cached snapshot of your test database instead of running migrate:fresh.

Refresher

A drop-in replacement for Laravel's RefreshDatabase that restores a cached snapshot of your test database instead of running migrate:fresh.

Kiln: Artisan commands and an optional signed HTTP route to clear, warm and inspect OPcache when you deploy.

Kiln

Artisan commands and an optional signed HTTP route to clear, warm and inspect OPcache when you deploy.

Laravel Media Viewer: Show private PDFs, video and audio from any Laravel disk without making the files public.

Laravel Media Viewer

Show private PDFs, video and audio from any Laravel disk without making the files public.

Laravel Swiper: Swiper sliders, carousels and image galleries for Laravel as Blade components.

Laravel Swiper

Swiper sliders, carousels and image galleries for Laravel as Blade components.

Laravel MySQL Advisor: Read-only health checks for the MySQL or MariaDB database behind your Laravel app, with the SQL and the Laravel migration to fix a problem wherever a fix applies.

Laravel MySQL Advisor

Read-only health checks for the MySQL or MariaDB database behind your Laravel app, with the SQL and the Laravel migration to fix a problem wherever a fix applies.

Laravel Webhook Console: A dashboard and replay tool for the webhooks spatie/laravel-webhook-client stores in your Laravel app.

Laravel Webhook Console

A dashboard and replay tool for the webhooks spatie/laravel-webhook-client stores in your Laravel app.

Laravel Pennant Dashboard: A browser dashboard for laravel/pennant feature flags: per-scope toggles, sticky percentage rollouts, purge and an audit log.

Laravel Pennant Dashboard

A browser dashboard for laravel/pennant feature flags: per-scope toggles, sticky percentage rollouts, purge and an audit log.

Laravel Notification Inbox: Catches every non-mail Laravel notification in local and staging instead of sending it, and shows each one as it would look on the other end.

Laravel Notification Inbox

Catches every non-mail Laravel notification in local and staging instead of sending it, and shows each one as it would look on the other end.

Laravel WebPush Kit: The browser side of Laravel web push: a subscribe button with a two-step permission prompt, a service worker, and routes that save each user's subscription. Tested in Chrome so far.

Laravel WebPush Kit

The browser side of Laravel web push: a subscribe button with a two-step permission prompt, a service worker, and routes that save each user's subscription. Tested in Chrome so far.

Laravel Redis Advisor: Read-only health checks for the Redis or Valkey behind your Laravel cache, queues, sessions and Horizon, with the redis.conf line or Laravel config that fixes each problem.

Laravel Redis Advisor

Read-only health checks for the Redis or Valkey behind your Laravel cache, queues, sessions and Horizon, with the redis.conf line or Laravel config that fixes each problem.

Need something built?

Free quote in 60 seconds