Hacker News new | comments | show | ask | jobs | submit login
What, why and how of PHP Composer (laravelfactory.com)
77 points by laravelfactory 4 months ago | hide | past | web | favorite | 61 comments

The Composer project and Packagist are the catalysts which made it possible to drag PHP development out of the dark ages, but it's still got some rough edges that will eat a afternoon.

Recent example: Re-organizing namespaces and classes in an internal library. Losing my mind (doing everything right) until finally realizing Composer wasn't updating the autoloader to reflect changes to the lib's composer.json.

For something that works really well when it’s working, I have blown a lot of hours fighting with this stuff.

In the future, if/when you change your namespaces or add new Class files, just run:

`composer dump-autoload`

This will dump the autoloader and rebuild it. This is much much faster than an entire `composer install` run. For additional usage options try:

`composer help dump-autoload`

* Unrelated: HN can we please get better markdown?

It generates a map file when you run `composer install` and many of the several other commands.

Yours is not really a critique of composer, since it's not a daemon or a continuously run script. You run it once and done.

No, it is though, because other package managers are not daemons and they don't have this problem.

Composer is optimized for how php executes which is once per request. If you want to compute namespaces per request that's your choice.

If you wish to daemonize it have a file change listener run it when it observes file system changes in the appropriate directory. If that is too much work a quick hack would be:

    watch -n 10 composer dumpautoloaf --no-scripts &

Full disclosure: I did not verify this command would work well

Rebuilding the autoloader became a normal step in diagnosing issues for me. You never know... These days I deal with npm which in some ways is nicer yet it can still eat afternoons.

So far no issues with PHP other than the occasional turn it off and back on again.

NPM? Wake up on a saturday morning and hot reload + react tools no longer works? F me.

On the bright side I almost finished the front end, so I can casually mess around with the solution every few days as I do my daily work in laravel.

Haha, fair enough. The other day I was getting this bizarre mismatch of versions of a dependency and I couldn't figure out how it could even matter. Like, who cares if they're two minor versions apart? Neither of them were global so there was no conflict for their parent modules. _That_ is the kind of stuff that kills me about npm. It can be really reeeaally hard to figure out what to do in those situations.

Also, package.json is arguably a pretty gnarly way to organize... Well, everything? It's the kitchen sink of configuration, but it's supposed to be for managing packages. But no, you can also configure your packages in there, configure scripts for your application, etc. It's nuts.

Even so, both of them are miles ahead of what we had 10 years ago!

Phpstorm is a good investment.

Sounds interesting, how does it help with Composer?

If you rename a class through PHPStorm, it will go through the entire codebase, find the old name and update it, including in the autoloaded class maps and files.

The short version:

If you're a PHP developer, here's why you should use a package manager instead of downloading zip-files.

Apparently Wikipedia, Facebook, Slack are not enough to convince some of PHPs credentials. But add a badly designed package manager that replicates all the problems in Ruby and NPM and suddenly PHP is 'interesting' again.

This just reflects the warped incentives of a community more interested in hype, resume padding and currying influence in ecosystem with questionable package managers and frameworks than any technical scrutiny.

PHP was always simple to setup and use, the system package manager has all the extensions. App deployment was a breeze anyone could do it. On the other hand with Ruby or Node you need a full build environment, compilation and dependency hell just to deploy apps. Yet according according to some its PHP that is 'in the dark ages'. See the warped incentives and user hostile behavior.

It difficult to see how this makes PHP better and hopefully it's attempt to 'gain respect' will not take it down the same path.

PHP was always simple to setup and use, the system package manager has all the extensions.

Sorry if I misunderstood what you're trying to say but this makes no sense to me. It's still the same simplicity to install PHP. But what you do with the package manager is not the same thing as what you achieve with composer. PHP extensions != PHP libraries.

You can also use the package manager to install python, ruby, perl, etc. What you generally don't do is use the package manager to install random 3rd party libraries (unless it's a really big project that's been packaged. e.g.: phpmyadmin)

Surely you wouldn't want php library maintainers to also create deb's and rpm's of their projects and host their own repositories, deal with distro release politics and other hindrances just so you can use apt or yum to install them?

Although composer was inspired by npm - they are not identical. Composer always just works for me. But with npm I always end up in some strange dependency hell. Add the fact that JS standard library is lacking in some basic functionality and you end up with a ludicrous amount of dependencies.

In short, give composer a try if you are already building apps in PHP.

While PHP core and officially sanctioned extensions have long been bundled in source and binary distributions there has also been PECL and PEAR.

I started writing code (mainly PHP) around 4 years ago. I've never known anything else than composer and package managers in general, and it blows my mind when people dont use them

I could be wrong but I thought most people who use PHP today were using it back before composer and PHP namespaces were even a thing.. Unless maybe you're working in Wordpress land, which I'm not sure has really adopted the practice of namespaces.

Out of curiosity, what made you choose PHP as a primary language 4 years ago?

After using Composer for some years I think these tips are good to think about:

  * Use full version numbers for your dependencies.
  * Include the vendor folder in your VCS.
The last one I had to think about a lot but it's a real pain to get an old project working again when dependencies are no longer available. Unfortunately this happens a lot.

Major and minor versions usually are sufficient, as you can lock to a specific version anyway.

You should never VCS the vendor directory. If you are concerned about disappearing 3rd party dependencies, you should:

- have a local cache - keep e.g. git mirrors for 3rd party dependencies - invest a bit more time in selecting dependencies with higher quality.

I've seen repos with vendors checked in. A few years, hundreds of thousands of commits, and even a git status takes 30 seconds to run.

Just saying, there is a more sensible approach that beats storing vendors in the project :-)

"and even a git status takes 30 seconds to run"

That's a problem with your vcs, not with the (defensive) practice of tracking external dependencies.

While sensible advice, usually only the VCS approach works across many organizations, which don't provide the resources to do it in any other more reasonable way.

Checking your dependencies in is a good idea. When you check out a version from some time ago, you won't have to worry if those versions are still available in your cache or on remotes. Especially if the package manager is not very dependable. Furthermore, if you patch or edit your dependencies, that information is permanently recorded too.

At my job we almost never version control our vendor directory, but you have a very strong point, and I am not strongly in our camp. One pain point in particular, is that if you are using Git Bisect to find out where a bug appeared, and you don't have your dependencies version controlled, you either have to run "composer install" at each bisect step, or set up an equivalent checkout hook. And while I guess the checkout hook could work, it is going to make a lot of other work a lot slower.

If `git status` is literally taking 30 seconds to run, it's not because you checked in your vendor dir lol.

Seriously, version control systems are specifically built to handle that kind of thing. You're mistaken as to the cause of your perceived slowdown.

Never say never, either. You don't know my life.

Instead of including the vendor folder into projects you may use satis [0] to "mirror" all of your dependencies. That means you will not have any broken stuff if packagist is down or any of your dependencies are missing.

[0]: https://github.com/composer/satis

IMO for the first point you should rather use ^x.y with the minimum version you require and then accept new releases as they come. If you do regular updates you should notice quickly when something break and be able to revert that update easily. If you update 20 packages at once it becomes harder to pinpoint where a regression occurred.

As for including the vendor dir in your VCS repo, this comes with quite a few drawbacks. That's one of the things Private Packagist (https://packagist.com) aims to fix though, as it keeps mirrored copies of your dependencies' zip archives so you get more reliable installs.

What guarantees you that packagist will be around in e.g. 15 years when you would like to start some old project?

If you are talking about such long time frames, then indeed archiving a project with its vendor directory might be a good idea once you decide to relegate it to the freezer.

How about "vendor decided to migrate off Github last week, and managed to break all their tags in the process"? (Not that this would have actually happened to me this Monday, noooo ;)) Long timeframes are not the only issue with external dependencies...

You don't need (and shouldn't depend on) packagist when using Composer. You can import packages directly from Github, Bitbucket, etc., or even locally, you just have to write a bit more JSON.

What do you suggest when the package you are using is pulling in other packages from packagist?

Rewrite your composer.json to include them directly?. The lock file probably contains the actual repository URLS so once you have a dependency tree resolved you can rewrite it based on that.

But it is possible to avoid packagist. Ugly and painful maybe but possible, and YMMV regarding the effort being worth the reward. Dependency management in PHP isn't (or shouldn't be) like it is with JS/Node where there is one authoritative registry that everyone has to depend on and that can assert direct influence over the community as a result. Packagist shouldn't be the PHP package registry, but a registry.

The fact that I need packagist, and the basic structure is really easy to copy? If not packagist, then someone will have set up a package repository with a different name.

> * Use full version numbers for your dependencies.

The tradeoff for this approach is to have to resolve version conflicts manually anytime there is more than minor dependency changes.

In particular, adding a package that is newer than most of your dependencies can be a nightmare when you locked down all the working revisions of your libraries.

On one hand there is less drama about packages changing under one's feet, on the other hand part of composer's job is shifted back to the dev who does the package updates.

Personally I would advise a more balanced approach of allowing minor version changes and only block major ones.

You always choose a reliable dependency not something random. I never had similar experience or saw a project doing that.

You should only version composer.lock and composer.json files. Ignore vendor directory and leave that job to your build step in CI/CD...

That's why we have our own composer repository powered by satis. When set up correctly, it can be used as a "proxy" for packagist, ensuring you always have an installable version of your dependencies, even if they are not available via packagist anymore.

Most insightful comment on this thread. I'm looking into satis now, thank you!


Things disappear, or get deleted, or old versions get replaced for various reasons. There's no "reliable dependency". Even if you think something's reliable, sone deeper dependency may disappear. See npm and left-pad for example.

Committing vendor directory may or may not be a good idea. But having your own copy of all dependencies (current and past) is necessary.

> But having your own copy of all dependencies (current and past) is necessary.

Definitely! Git mirrors are cheap, and there are various solutions for composer proxies out there. If you consider CI/CD you will want freedom from external calls anyway.

Your build system should take care of this for you. For example, build a docker image or store an artifact (e.g. zip file) of the full build including dependencies. Then put it on your own docker registry or the artifact on S3, for example.

So I just wanted to try Laravel Factory. I was likely to buy it as I tried some Laravel CRUD builders in the past and each had some flaws that your project seems not to have. However, I couldn't complete registration as you don't allow disable throwaway domains. I just wanted to let you know it makes no sense whatsoever. I never disclose my real e-mail addresses at that stage. Just wanted to let you know - and also others who make the same mistake. If you don't want my money, that's OK.

It is quite possible that they have found that people who use disposable email accounts never buy anything. My company also blocks disposable email address because we found that people using them were just abusing our service and our sales went up after doing so.

The funny thing is apart from emailing the free code we almost never contact anyone since we know 99% of our free users are not potential paying customers and so there is no point wasting our time on them. We only know this because they give us their real email address which allows us to screen them out.

Maybe for some services that you can abuse blocking disposable addresses might make sense, but not for this one.

In any case, I finally decided to register using a throwaway spambox from Gmail instead of Mailinator (what difference does it make, really...) and it turns out the Laravel Factory is inferior to Voyager as it doesn't support roles out of the box. Which is a pity as other things have been solved quite nicely. I'll give it a try in a few months, maybe they catch up.

It is rather silly to block disposable addresses if you are going to allow free email services like gmail.

In our case we block all free and disposable email address since nobody without a corporate or university email address uses our service (it is aimed at scientists).

We used to let anyone use the service for free without registering for small scale use, but what we found were some commercial suppliers (our target market) were just telling their customers to use our free service rather than fork out the $0.02 it would have cost them to buy a license on assays they were selling for $10. Once cutoff from the ability to freeload, quite a number of these commercial suppliers decided to buy a license from us.

The good thing about this is not only did we get the business, but their customers got the benefit of our service automatically.

Just tested it myself with guerillamail and mailinator. And as you say, "Disposable email addresses are not allowed".

I get why they'd do this because obviously they want to capture potential buyers of their software to pester at a later date to buy but I'm not a potential buyer until I've tried it.

So I'm another one that won't be handing over any money.

We have removed the validation for disposable email addresses. Thank you for the feedback.

Initially, we used it just to make sure that system is not misused but we understand your concern and accept it.

We are also considering the roles part for authorization. Stay tuned. Thanks.

I read through this post and spent the morning reading more about Composer.

I've been on the fence for a while, but I'm still not sure yet if this is right for me.

Most of the projects I work on have minimal dependncies & existing autoloading strategies. While I would like to have access to new dependencies via Composer it seems like I'll be forced to engage in heavy refactoring to update namespaces and will need to somehow package my existing code.

Curious if anyone here has firsthand experience adding Composer to an existing project that wasn't dependency heavy?

You won't even notice it.

Everything you already have will continue to work fine. All you have to do is include the autoloader somewhere in your code path.

An example assuming you already installed composer on the machine into your /bin or similar directory.

# add a new dependency:

  composer require guzzlehttp/guzzle
# this dependency will now be in the vendor directory

  ls ./vendor
# update your apps entry point (ie: frontcontroller.php):

  // require composer's autoloader
  require ('vendor/autoload.php');
# autoload will now find any dependencies you add via composer

  // create guzzle client
  $client = new \GuzzleHttp\Client();
# another tip, if you already have a bunch of class files some where (ie: myapp/src/classes , myapp/src/models ) You can include class paths via composer.json

      "autoload": {
          "classmap": ["classes/", "models/", "MyClass.php"]
You can now remove any hard-coded include or require statements.

There is a lot more things you can do with it but this is the most basic example.

>There is a lot more things you can do with it but this is the most basic example.

One useful feature is custom commands[0].


Also, regarding autoloading, I find that once you get used to the structure of PSR-4, adding files to a PSR-4 namespace[1] and just having autoloading work is incredibly helpful. The only pain point is dealing with namespaces everywhere.


I use PHP Composer, but the fact that its logo is actually a conductor makes me cringe and wonder what else is fundamentally wrong with the product. Close enough for PHP, I guess ;0

There's a zero-width-joiner and then a space at the start of this title. It's

    ‍ What, Why and How of PHP Composer
The zwj doesn't print (of course) but the space does, causing the alignment of titles on the front page to be slightly off. It tweaked me.

Always looking out for the important things...

This is the only reason I decided to click into the comments, even.

Wow, one more invisible character to worry about that does not get dealt with by a standard `.strip()`

And it won't show in our history...

These are important things! We've unsullied the title.

The fundamental problem with composer is it goes and updates everything even when I just want it to deal with a single package. And then, of course, because so many packages promise but can't keep proper semver, things break. Marvelous.

Coupled with arcane version syntax (Drupal's version system predates Composer and it used natural syntax like foo (>=2.1.1) bar (2.x) so all they needed to do is to take the about 30 lines of well commented code, no need to memorize a list of sigils but no), excruciating slowness makes me wish I never heard of it much less need to work with it daily.

Updating single packages is very much possible, see https://getcomposer.org/doc/03-cli.md#update - as for semver promises, that's really up to you and which packages you decide to trust, nothing the tool can do about it.

Note I said "deal with", it's not update, I learned long ago never to touch composer update. I think it is require that does this. Or that install doesn't have a single package argument? Whatever. I am not alone in finding the only way to actually use composer is to nail down every single package to a single version. Do note I didn't write https://github.com/webflo/drupal-core-strict which is just that https://github.com/webflo/drupal-core-strict/blob/8.5.4/comp...

As for trust, noone in the PHP world! Absolutely noone! I got into a debate with Rasmus about the meaning of backwards compatibility around the time PHP 5.4 began to throw additional warnings (not a new class of errors which could be additionally displayed, no) on code that previously worked. Drupal 8.4 released with a known bug that caused some code to merrily lose files uploaded by users because of a BC break. If you want BC, look at the kernel Linux API and even the ABI.

> Or that install doesn't have a single package argument?

`composer require {vendor}/{your-amazing-package}:{version}`

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact