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.

Join 9,500+ smart developers

Get my monthly newsletter with what I learn from running Spatie, building Oh Dear, and maintaining 300+ open source packages. Practical takes on Laravel, PHP, and AI that you can actually use.

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

Found something interesting to share? Submit a link to the community section.