Calculating distance using MySQL

Logan Henson, a developer at Tighten, wrote a new post on the company blog about MySQL's cool ST_Distance_Sphere function.
On a client project recently, we had to make it easy to filter database query results based on the distance between a user and an entity in our database. It's easy to get overwhelmed in that context, worrying about the crazy amount of PHP calculations you're going to have to run. ... If you need to calculate this, you can actually get surprisingly far by just using MySQL!
https://tighten.co/blog/a-mysql-distance-function-you-should-know-about

Why using Yoda conditions you should probably not be

Grégoire Paris wrote down his opinion on why he dislikes Yoda conditions.
So how do Yoda conditions work? Well it is basically a knee-jerk reaction you have to develop: whenever you write a condition, put the operand that cannot be assigned on the left. This should give you an error message if you make an assignment when you actually meant to make a comparison.
https://dev.to/greg0ire/why-using-yoda-conditions-you-should-probably-not Personally, I'm not a big fan of Yoda conditions either. My feeling is the the cost of decreased readability is just too high for the small value that Yoda conditions bring to the table.

Cruddy by design

At this year's Laracon US Adam Wathan gave a talk titled "Cruddy By Design" on how to structure your controllers better. After the conference he published a new GitHub repo that contains the demo app he refactored on stage. The 4 main tips to improve your code come as PRs on the repo with a full description on why the change is valuable. Very cool stuff.
Using this convention as a "rule" is a good way to force yourself to keep your controllers from becoming bloated, and can often lead to learning interesting new things about your domain. For the presentation, I put together a demo app called "CastHacker" that showcases podcasts about software development. It's not a "real" app by any means (lots of imaginary features, no tests, etc.); it's just enough code to demonstrate the concepts from the presentation. Feel free to clone it and play with it locally if you like though. I've written up each refactoring I shared in the presentation as a detailed pull request.
https://github.com/adamwathan/laracon2017

Generate pdfs with Google Chrome on a Forge provisioned server

While working on one of our projects my colleague Sebastian had to create a pdf with some text and charts. In a new post on his blog he explains how he leveraged headless Chrome to create the pdf.
This week I needed to export some charts generated with HTML & JavaScript as a pdf file. I already had implemented the charts on a webpage so I wanted a solution that allowed me to use my existing code for the pdfs. Headless Chrome to the rescue! Chrome can run as a cli tool, and print a pdf file from a url. Al I had to do was make some layout tweaks to make everything printer-friendly.
https://sebastiandedeyne.com/posts/2017/generate-pdfs-with-google-chrome-on-a-forge-provisioned-server Meanwhile support for creating pdfs has been added to our Browsershot package (which also uses headless Chrome under the hood). Here's how you can convert a webpage to a pdf using the package:
Browsershot::url('https://example.com')->save('example.pdf');

A tool to automatically rerun PHPUnit tests when source code changes

In the JavaScript world Jest, built by Facebook, is an excellent tool to run tests. Not only can it automatically rerun your tests when source code changes, but there's also an interactive mode where you can set a filter on which tests to run while the tool is running. Would it be great if we could have these awesome features while working with PHPUnit? Our newly released phpunit-watcher tool provides a Jest like experience. You can simply install it by running composer global require spatie/phpunit-watcher. When you start it with phpunit-watcher watch this is what it looks like. By default it will watch all files in the src, app and tests subdirectories in the directory where it is started. If any of the files in those directories changes (or when a file in there gets created or deleted) the tests will rerun automatically. Cool, right? If you need to watch another directory just add a file named .phpunit-watcher.yml in your project directory. Here's some example content:
watch:
directories:
- myApplication
- tests
fileMask: '*.php'
Extra options can be passed to PHPUnit just by tacking them on the phpunit-watcher command. Here's an example where we only run tests whose name contains the word "includes": Now, if you want to get rid of that filter, there's no need to stop the tool. Like the little manual at the bottom will tell you, just press "a" to run all tests again. If you only want to run tests in a specific file or path, just type "p" to get to this screen: On that screen, just type the name of the file or directory that you want to filter on. And that's all there's really to it. The tool is fairly new, but the past days I've really enjoyed using our own tool myself and I wonder how I could ever have worked without it. Now I know that some IDE's, such as PHPStorm, ship with a PHPUnit watcher built-in, but our tool feels nicer (that's very subjective of course) and will work in combination with any editor or IDE (that's very objective). Some cool packages are powering our tool. The watching part is covered by the awesome Resource-watcher package. The interactivity is enabled by ReactPHP. I also want to give a shoutout to Colin O'Dell who helped fix a nasty performance problem and Christoper Pitt who wrote a nice blogpost that kickstarted the work on this package. If you want to know more about phpunit-watcher, be sure to check it out on GitHub. This is not the first time we've created something inspired by Jest. Take a look at this package which brings Jest's snapshot testing to PHPUnit. Want to see some mooarrrr packages we created previously, then check out the opensource pages on our company website.

How to write JavaScript-style test watchers in PHP

Christoper Pitt published another excellent piece over at Sitepoint. This time he describes how he built a watcher to automatically recompile his preprocessed code and rerun the tests.
In order to reduce the burden of invoking the transformation scripts, boilerplate projects have started to include scripts to automatically watch for file changes; and thereafter invoke these scripts. These projects I’ve worked on have used a similar approach to re-run unit tests. When I change the JavaScript files, these files are transformed and the unit tests are re-run. This way, I can immediately see if I’ve broken anything.
https://www.sitepoint.com/write-javascript-style-test-watchers-php/

Diving into Laravel Horizon

Laravel Horizon is a kickass dashboard for viewing queued jobs. Co-creator Mohammed Said published two posts about the inner working of the tool. The first one on the Diving Laravel site highlights the overall configuration and how the master supervisor works.
Laravel Horizon is a queue manager that gives you full control over your queues, it provides means to configure how your jobs are processed, generate analytics, and perform different queue-related tasks from within a nice dashboard. In this dive we're going to learn how Horizon boots up and handles processing jobs using different workers as well as how it collects useful metrics for you to have the full picture of how your application dispatches and runs jobs.
https://divinglaravel.com/horizon/before-the-dive The second one, published on his own blog, shows how queued jobs can get tagged.
Laravel Horizon is shipped with many amazing features that help you understand what goes on with your queue workers, my personal favorite feature is the ability to tag jobs for further investigation.
https://themsaid.com/tagging-jobs-in-laravel-horizon-20170731

How to analyze tweet sentiments with PHP Machine Learning

In a post on Sitepoint Allan MacGregor gives a good practical example on how to work with PHP-ML, a machine learning library for PHP.
As of late, it seems everyone and their proverbial grandma is talking about Machine Learning. Your social media feeds are inundated with posts about ML, Python, TensorFlow, Spark, Scala, Go and so on; and if you are anything like me, you might be wondering, what about PHP? Yes, what about Machine Learning and PHP? Fortunately, someone was crazy enough not only to ask that question, but to also develop a generic machine learning library that we can use in our next project. In this post we are going take a look at PHP-ML – a machine learning library for PHP – and we’ll write a sentiment analysis class that we can later reuse for our own chat or tweet bot.
https://www.sitepoint.com/how-to-analyze-tweet-sentiments-with-php-machine-learning/

Achieving Geo-search with Laravel Scout and Algolia

On Scotch.io a new post by Julien Bourdeau was published that shows how you can easily import and search geographic data with Laravel Scout and Algolia.
Laravel Scout makes it very easy to setup an external search engine to create consumer-grade search quickly. The package comes with Algolia as a default search engine. I'd like to demonstrate how to make use of the geo-location search feature with Scout. In this tutorial, you'll learn how to prepare your data for Algolia and Laravel Scout to retrieve items based on location.
https://scotch.io/tutorials/achieving-geo-search-with-laravel-scout-and-algolia

Optimize images in Laravel apps

A while ago we released image-optimizer. In short this package can make all kinds of images smaller by stripping out metadata and applying a little bit of compression. Read this blogpost to learn more about it. Although it's pretty easy to work with the package, we felt that we could deliver a more seamless experience in Laravel apps. That's why we created our newly released laravel-image-optimizer package. The package uses a bunch of binaries to optimize images. To learn which ones and how to install them, head over to the optimization tools section in the readme of the underlying image-optimizer package. That readme also contains info on what these tools will do to your images. Once the laravel-image-optimizer package is installed it's laughably easy to optimize images. If you like facades this is how you'd go about it:
use ImageOptimizer;

// the image will be replaced with an optimized version which should be smaller
ImageOptimizer::optimize($pathToImage);

// if you use a second parameter the package will not modify the original
ImageOptimizer::optimize($pathToImage, $pathToOptimizedImage);
You don't like facades you say? No problem! Just resolve a configured instance of Spatie\ImageOptimizer\OptimizerChain out of the container:
app(Spatie\ImageOptimizer\OptimizerChain::class)->optimize($pathToImage);
The package also contains a middleware to automatically optimize all images in a request.
Route::middleware('optimizeImages')->group(function () {
    // all images will be optimized automatically
    Route::post('upload-images', '[email protected]);
});
If you want to customize the chain of tools and the options being passed to them, you can do so by publishing and modifying the config file. This is the default contents:
use Spatie\ImageOptimizer\Optimizers\Svgo;
use Spatie\ImageOptimizer\Optimizers\Optipng;
use Spatie\ImageOptimizer\Optimizers\Gifsicle;
use Spatie\ImageOptimizer\Optimizers\Pngquant;
use Spatie\ImageOptimizer\Optimizers\Jpegoptim;

return [
    /*
     * When calling `optimize` the package will automatically determine which optimizers
     * should run for the given image.
     */
    'optimizers' => [

        Jpegoptim::class => [
            '--strip-all',  // this strips out all text information such as comments and EXIF data
            '--all-progressive',  // this will make sure the resulting image is a progressive one
        ],

        Pngquant::class => [
            '--force', // required parameter for this package
        ],

        Optipng::class => [
            '-i0', // this will result in a non-interlaced, progressive scanned image
            '-o2',  // this set the optimization level to two (multiple IDAT compression trials)
            '-quiet', // required parameter for this package
        ],

        Svgo::class => [
            '--disable=cleanupIDs', // disabling because it is know to cause troubles
        ],

        Gifsicle::class => [
            '-b', // required parameter for this package
            '-O3', // this produces the slowest but best results
        ],
    ],

    /*
     * The maximum time in seconds each optimizer is allowed to run separately.
     */
    'timeout' => 60,

    /*
     * If set to `true` all output of the optimizer binaries will be appended to the default log.
     * You can also set this to a class that implements `Psr\Log\LoggerInterface`.
     */
    'log_optimizer_activity' => false,
];
To learn more about laravel-image-optimzer head over to the readme on GitHub. And be sure to check out the other Laravel package we've previously made.

Combining query scopes with explicit model names

Typehint all the things

David Négrier, CTO of the CodingMachine, wrote a nice article on why he likes and how his team uses typehints.
As a developer consuming this function, I know how to use it. And if I’m using it wrong, I’ll know right away because PHP will crash with a nice error message when the function is called rather than with a cryptic error some time later.
https://www.thecodingmachine.com/type-hint-all-the-things/ Personally I like typehints too, because the potential readability improvement the article touches upon. Note: (I only include this paragraph because it's mentioned in the intro of the article, don't want to stir up a discussion) the fuzz about that "Visual Debt" video was overblown. Even though I didn't agree with all of it, it was nice to hear Jeffrey's way of thinking.

Easily optimize images using PHP (and some binaries)

Our recently released image-optimizer package can shave off some kilobyes of PNGs, JPGs, SVGs and GIFs by running them through a chain of various image optimization tools. In this blog post I'll tell you all about it. First, here's a quick example on how you can use it:
use Spatie\ImageOptimizer\OptimizerChainFactory;

$optimizerChain = OptimizerChainFactory::create();

$optimizerChain->optimize($pathToImage);
The image at $pathToImage will be overwritten by an optimized version which should be smaller. Here are a few images that were optimized by this package.

Why we built this

On nearly every website we make, images are displayed. In fact, in most cases images make up the bulk of the size of the entire page. So to provide a fast page load it's best to make those images as small as they can be. The less bytes the browser needs to download the faster the page will be. Now, to make images as small as they can be (without sacrificing a lot of detail) there are a lot of tools available. These tools, such as jpegtran, pngquant, and gifsicle, work more or less by applying a little bit of compression, removing metadata and reducing the number of colors. In most cases these tools can make your images considerably smaller without you noticing, unless you have a trained eye for that. These tools are free to use and can be easily installed on any system. So far so good. What makes them a bit bothersome to use from PHP code is that you need to create a process to run them. You must make sure that you pass the right kind of image to the right optimizer. You also have to decide which optimization parameters you're going to use for each tool. None of this is rocket science, but I bet that the vast majority of small to medium sites don't bother writing this code or researching these optimizations. Our package aims to do all of this out of the box. It can find out which optimizers it should run, it can execute the binary and by default uses a set of optimizers with a sane configuration.

How to optimize images

Optimizing an image is very easy using our package.
use Spatie\ImageOptimizer\OptimizerChainFactory;

$optimizerChain = OptimizerChainFactory::create();

$optimizerChain->optimize($pathToImage);
The image at $pathToImage will be overwritten by an optimized version which should be smaller. The package will use these optimizers if they are present on your system: The readme of the package includes instructions on how to install these on Ubuntu and MacOS.

Which tools will do what?

Like already mentioned, the package will automatically pick the right tool for the right image.

JPGs

JPGs will be made smaller by running them through JpegOptim. These options are used: - --strip-all: this strips out all text information such as comments and EXIF data - --all-progressive: this will make sure the resulting image is a progressive one, meaning it can be downloading using multiple passes of progressively higher details.

PNGs

PNGs will be made smaller by running them through two tools. The first one is Pngquant 2, a lossy PNG comprossor. We set no extra options, their defaults are used. After that we run the image throug a second one: Optipng. These options are used: - -i0: this will result in a non-interlaced, progressive scanned image - -o2: this set the optimization level to two (multiple IDAT compression trials)

Customizing the optimization

If you want to customize the chain of optimizers you can do so by adding Optimizers manually to a OptimizerChain. Here's an example where we only want optipng and jpegoptim to be used:
use Spatie\ImageOptimizer\OptimizerChain;
use Spatie\ImageOptimizer\Optimizers\Jpegoptim;
use Spatie\ImageOptimizer\Optimizers\Pngquant;

$optimizerChain = (new OptimizerChain)
   ->addOptimizer(new Jpegoptim([
       '--strip-all',
       '--all-progressive',
   ]))

   ->addOptimizer(new Pngquant([
       '--force',
   ]))
If you want to use another tool than the package supports out of the box, you can easily write your own optimizer. An optimizer is any class that implements the Spatie\ImageOptimizer\Optimizers\Optimizer interface. If you want to view an example implementation take a look at the existing optimizers that ship with the package.

Integration in other packages

Our image-optimizer is not the first package we wrote the revolves around handling images. There also our image package which makes modifying images very easy. And we have laravel-medialibrary which can associate all kinds of files (including images) with Eloquent models. And lastly we have Browsershot, which can turn any webpage into an image. Let's take a look on how image-optimizer has been integrated in all of those.

Image

Using the image package you can manipulate an image like this:
Image::load('example.jpg')
    ->sepia()
    ->blur(50)
    ->save();
This creates a sepia version that is blurred. The package has many other available manipulations. Here's how you can create an optimized version.
Image::load('example.jpg')
    ->sepia()
    ->blur(50)
    ->optimize()
    ->save();
Yea, just add the optimize method in the chain and you're done. Easy right?

laravel-medialibrary

In laravel-medialibrary this is just as easy. Using that package you can define conversion profiles on your models. Whenever you associate a file with that model a derived file using that conversion profile is being generated. This is handy for creating thumbnails and such. Here's a quick example of such a conversion profile.
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia\Interfaces\HasMediaConversions;
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;

class NewsItem extends Model implements HasMediaConversions
{
    use HasMediaTrait;

    public function registerMediaConversions()
    {
        $this->addMediaConversion('thumb')
              ->width(368)
              ->height(232)
              ->sharpen(10);
    }
}
Let's add an image to the medialibrary:
$media = NewsItem::first()->addMedia($pathToImage)->toMediaCollection();
Besides storing the original item, the medialibrary will also create a derived image.
$media->getPath();  // the path to the where the original image is stored
$media->getPath('thumb') // the path to the converted image with dimensions 368x232

$media->getUrl();  // the url to the where the original image is stored
$media->getUrl('thumb') // the url to the converted image with dimensions 368x232
That's a crash course into using medialibrary. But wait, we didn't create an optimized version of that thumbnail. Let's do that now. Under the hood all conversions are done by the aforementioned image package. So you can just use optimize function in your conversion profile.
    public function registerMediaConversions()
    {
        $this->addMediaConversion('thumb')
              ->width(368)
              ->height(232)
              ->sharpen(10)
              ->optimize();
    }
Boom done. In the next major version of medialibrary we'll automatically call optimize behind the screens for all image conversions. So you'll get optimized conversion by default. We'll add a nonOptimized method if you want to opt out of that. We haven't introduced that behaviour in the current version because it's breaking change.

Browsershot

Browsershot is a package that leverages headless Chrome to turn any webpage into an image. Here's how to use it:
Browsershot::url('https://example.com')->save($pathToImage);
And here's how to save an optimized version:
Browsershot::url('https://example.com')->optimize()->save($pathToImage);

In closing

I should mention that our optimize package is based upon another one by Piotr Śliwa. All the basic principles on how the package should work are inspired by Piotr's work. The reason why we rewrote it is because his was not that easy to extend and did not use modern stuff such as Symfony's Process component or PSR-3 compatible logging. In this post I've mainly mentioned tools you can install locally, but there actually are a lot of SaaS solutions as well such as TinyPNG, Kraken.io, imgix.com and many many others. In this first release of our image-optimizer package I've mainly concentrated on supporting local optimizers. With remote optimizers you have to deal with slowness of the network and API keys and such. But I do recognize the value of those remote services. That's why you'll probably see some remote optimizers being referenced or included in package in the future. Here's an issue on the repo where the first thoughts on that were being exchanged. The package contains a few more features not covered by this blogpost. So check out image-optimizer on GitHub. I hope our tool can make your images smaller and your pages faster. If you haven't already done so, check out our previous work in the open source space. Please send us a postcard if any of our stuff makes in into your production environment.

A list of podcasts

On his blog Left On The Web, Stefan Koopmanschap lists the podcasts he's listening to. His selection contains both tech and non-tech podcasts.
I had sitting in travel not being able to do anything. Listening to music can help, but can end up also being frustrating. While I was working at Schiphol last year I got pointed to podcasts. Since then I've been really getting into listening to podcasts on my daily commute and it's been making the trip a lot more fun... and useful. Here is a random collection of podcasts that I've been listening to in the past year and a half, on many different subjects. My main problem right now is that it's so many that I'm way behind on the episodes of most of these. Ah well, it's still quite good content.
https://leftontheweb.com/blog/2017/07/01/a-list-of-podcasts/ Here are a few of my favourite podcasts: North Meets South In this relatively young podcast Jacob Bennett and Michael Dyrynda talk about the things that make them tick. Twenty Percent Time Daniel Coulbourne & Caleb Porzio weekly discuss a programming topic. They try to keep it to twenty minutes, but that doesn't always work out that way :-) The Laravel News podcast Besides North Meets South, Jacob and Michael also run another podcast focused on all things happening in the Laravel ecosystem. Full Stack Radio Adam Wathan & David Hemphill talk about how they are creating their products: Crondog & KiteTail Voices Of The Elephant In this podcast Cal Evans interviews people active in PHP community. It's been a while since there was a new episode, but it's still worthwhile to listen to. The Changelog Adam Stacoviak & Jered Santo weekly have a conversion with somebody from the open source community.

Easily convert webpages to images using PHP

Browsershot is a package that can easily convert any webpage into a image. Under the hood the conversion is made possible new headless options in Chrome 59. In this post I'd like to show you how you can use Browsershot v2. Here's a quick example of how it can be used:
Browsershot::url('https://example.com')->save($pathToImage);

History

About three years ago I started working on my first package, called Browsershot. It can convert any webpage to an image. Under the hood PhantomJS was used to perform the transformation. Since it got released it did it's job pretty well, but unfortunately PhantomJS recently has been abandoned. A few weeks ago Chrome 59 got released. In that version some pretty cool features were introduced. One of them is the ability to take screenshots of a webpage. A recent version of Chrome probably is better in rendering a correct page then and abandoned version of PhantomJS. That's why I decided to make a new major release of Browsershot. In this post I'd like to show you how you can use Browsershot v2.

Installing Chrome 59

In order to make use of Browsershot you must make sure that Chrome 59 or higher is installed on your system. On a Forge provisioned Ubuntu 16.04 server you can install the latest stable version of Chrome like this:
sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
sudo apt-get update
sudo apt-get -f install
sudo apt-get install google-chrome-stable
Browsershot has been tested on MacOS and Ubuntu 16.04. If you use another OS your mileage may vary.

Using Browsershot

Here's the easiest way to create an image of a webpage:
Browsershot::url('https://example.com')->save($pathToImage);
Browsershot will make an education guess where Google Chrome is located. If on your system Chrome can not be found you can manually hint it's location:
Browsershot::url('https://example.com')
   ->setChromePath($pathToChrome)
   ->save($pathToImage);
By default the screenshot will be a png and it's size will match the resolution you use for your desktop. Want another size of screenshot? No problem!
Browsershot::url('https://example.com')
    ->windowSize(640, 480)
    ->save($pathToImage);
You can also set the size of the output image independently of the size of window. Here's how to resize a screenshot take with a resolution of 1920x1080 and scale that down to something that fits inside 200x200.
Browsershot::url('https://example.com')
    ->windowSize(1920, 1080)
    ->fit(Manipulations::FIT_CONTAIN, 200, 200)
    ->save($pathToImage);
In fact, you can use all the methods spatie/image provides. Here's an example where a greyscale image is created:
Browsershot::url('https://example.com')
    ->windowSize(640, 480)
    ->greyscale()
    ->save($pathToImage);
If, for some reason, you want to set the user agent Google Chrome should use when taking the screenshot you can do so:
Browsershot::url('https://example.com')
    ->userAgent('My Special Snowflake Browser 1.0')
    ->save($pathToImage);

In closing

The screenshot capabilities of Chrome are already quite good, but there's a lot of room for improvement still. Right now there's no way to specify where Chrome should save the screenshot (a problem that the package solves for you behind the scenes). In the DevTools there's an option to take a screenshot of the whole length of the page. Unfortunately this isn't possible with the current command line options. I'm pretty sure the headless and screenshotting options will improve in future versions of Chrome. I intend to update Browsershot as soon as new features become available in Chrome. Want to get started using Browsershot? Then head over to GitHub. Also take a look at the other packages our team has previously made.