Oh Dear is the all-in-one monitoring tool for your entire website. We monitor uptime, SSL certificates, broken links, scheduled tasks and more. You'll get a notifications for us when something's wrong. All that paired with a developer friendly API and kick-ass documentation. O, and you'll also be able to create a public status page under a minute. Start monitoring using our free trial now.

Getting package statistics from Packagist

Original – by Freek Van der Herten – 2 minute read

At my work I'm currently creating a new dashboard. That's a fancy term for an html page sprinkled with some Vue magic that will be displayed on tv screen at the wall of our office. I won't say much about the dashboard itself on this post, but I'll make sure to write something on that in the near future.

One of the things I want to display on our dashboard is how many times our packages get downloaded (yeah it's a vanity project, sorry about that :-)). To make this real easy our intern Jolita and I cooked up a new package called packagist-api. It uses the packagist api to fetch data about published packages.

Once installed you can to this:

$client = new \GuzzleHttp\Client();

$packagist = new \Spatie\Packagist\Packagist($client);

//returns a list of all packages by a vendor
$packagist->getVendorPackages('spatie');

//returns statistics on a specific package
$packagist->findPackageByName('spatie/laravel-fractal');

That last call will return a big array with all info on a given package:

[
     "package" => [
       "name" => "spatie/laravel-fractal",
       "description" => "A Fractal service provider for Laravel 5",
       "time" => "2015-10-06T13:33:09+00:00",
       "maintainers" => [
         [
           "name" => "spatie",
         ],
       ],
       "versions" => [
         "dev-master" => [
           "name" => "spatie/laravel-fractal",
           "description" => "A Fractal service provider for Laravel 5",
           "keywords" => [

...

       "downloads" => [
         "total" => 18844,
         "monthly" => 4859,
         "daily" => 18,
       ],
       "favers" => 142,
     ],
   ]

This code will get the daily, monthly and total number of downloads for our packages:

$totals = collect($packagist->getPackagesByVendor('spatie')['packageNames'])
    ->map(function ($packageName) use ($packagist) {
        return $packagist->findPackageByName($packageName)['package'];
    })
    ->reduce(function ($totals, $packageProperties) {

        foreach ($totals as $sumName => $total) {
            $totals[$sumName] += $packageProperties['downloads'][$sumName] ?? 0;
        }

        return $totals;
    }, ['daily' => 0, 'monthly' => 0, 'total' => 0]);

This will output this array:

[
  "daily" => 423
  "monthly" => 94876
  "total" => 473184
]

Now the only thing that's bothering me is that foreach-loop in the reduce. Hopefully after reading Adam Wathan's new book on refactoring to collections I'll come up with a more elegant solution. If you have a suggestion on how to make the code better, let me know in the comments below.

EDIT: I did manage to get the code better using a pipe macro.

Share Post LinkedIn

I write about Laravel, PHP, AI and building better software.

Every two weeks, I share practical tips, tutorials, and behind-the-scenes insights from maintaining 300+ open source packages. Join thousands of developers who read along.

No spam. Unsubscribe anytime. You can also follow me on X.

Found something interesting to share?

The community section is a place where developers share links to articles, tutorials and videos. Submit a link and help fellow developers discover great content. As a thank you, you'll receive a coupon for a discount on Spatie products.