Require PHP packages without destroying whole dependencies

0
4559
Require PHP packages without destroying whole dependencies

Composer is the main PHP package manager that powers modern PHP development these days, but do you know how to leverage Composer in awkward PHP development moment? Let me show you a hack!

Crazy PHP development situations

While developing PHP projects, you will face some weird situations like these:

  • Authors stop spending on developing the packages. Your projects depends heavily on their packages, but they stop. You’re stuck!
  • You write some packages for projects, but you want to test them first without publishing to central repositories like Packagist.
  • You want to require a new package into composer.json but do not want to pollute current sharing composer.lock, which holds versions of all packages for projects.

You get confused and wonder what you could do in such situations.

I’ve experienced with those, so I’m writing this article to share the little trick I do often to avoid them.

Control PHP packages step-by-step

To solve all those issues, first, you need to get the source code into your Github account.

If original packages have Github or Gitlab or Bitbucket or whatever Git services, you need to fork them or put them on a public Git service. I do recommend to take advantages of Github, since it works best with composer.

Make tags or branches

Supposed that the original package named author/package, then you have to put the package (or fork) into your own Github account, so the Github url would be like https://github.com/user/package.git.

What you need to do next is to setup a version by tagging, that would make a release.

Be aware at versioning when you fork, because you need to make a later version than current. So if original package is at v3.0.12 then you could create a new version for your own repository like v3.0.13 after tweaking the source.

$ git tag -a 3.0.13 -m "Release version 3.0.13"
$ git push --tags

You can make a dev branch, too. That also works. So it can be like:

$ git checkout [LATEST_VERSION]
$ git checkout -b feature-X

Update composer.json

First you will need to add your Git url to the file.

"repositories": [
    {
        "type": "git",
        "url": "https://github.com/user/package.git"
    }
]

The repositories key in composer.json is to specify the location where to grab the package first before fallback into Packagist.

Require the package

Finally, you will need to import the package. Usually, developers will write necessary packages into composer.json then execute $ composer update.

But that causes a serious problem. That is, the command will refresh all latest appropriate versions of current packages in project and that will update composer.lock. And this is not what we want.

We only need to update one and only one package because of weird situations we’re dealing with.

Type following command to add new package into project if you release such a version

$ composer require author/package:3.0.13

or use following command if you use branches.

$ composer require author/package:dev-feature-X

As composer convention, you need to add dev- as prefix for versioning. So if your branch name is refactor, then the version to specify in the command is dev-refactor.

It seems weird but Composer works that way.

Also, make sure you require the correct package name which is defined in original package. Cloning original authors’ packages into your own Github repositories doesn’t mean the packages will be resolved in your Github account naming.

After that, you can verify if the packages has been updated in your projects. It should work anyway. Otherwise, please follow my instructions again from beginning.

Compatibility tricks

One of the most headache problem in development is the compatibility issue.

Let say we’ve been using another package on version v1.5.8 , the original package at the moment is at version v3.1.2. But we can’t upgrade yet due to many compatibility issue when moving from major version v1 to v3.

Now the problem is this. Somehow, at v3.1.1 author has found and fixed some security issues which are originated from v1. And the patch is applied to v3.1.2. We want to apply this patch too but we can’t afford to upgrade from v1 to v3. It’s a freaking long way to upgrade.

We can ask authors or even make PRs to apply the patch for v1. This normally works if the package is actively under development.

But if author rejects for some reasons like:

  • Author says his package being outdated to modern tech. Obsolete!
  • Author has no effort to maintain the package.
  • Author doesn’t want to keep updates for lower versions.
  • …etc.

So the only option left we can do is to make our own patch in our own repository.

  • Fork or clone into our Github account.
  • Jump to version 1.5.8, and create a new branch, ex. fix-v1-security.
  • Apply the patch and tag version 1.5.9.
  • Import into our projects either with branch dev-fix-v1-security or with version 1.5.9.

Conclusion

It is rarely for me to face with such crazy situations like this, but when there is, this is the hack I do.

It might not be the best way to do but it works. If you have better solutions, share to me. That would be very nice.