PHP Archives | Lee Willis https://www.leewillis.co.uk/tag/php/ Mon, 27 Mar 2017 16:06:25 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 Background processing for WordPress https://www.leewillis.co.uk/background-processing-wordpress/ https://www.leewillis.co.uk/background-processing-wordpress/#respond Mon, 27 Mar 2017 16:06:25 +0000 https://www.leewillis.co.uk/?p=959 I’m the maintainer of a reasonably well-used WooCommerce plugin that currently generates a full set of product data from a store This is currently done on-demand to make sure the information is up to date. On smallish stores, everything works just … Continue reading

The post Background processing for WordPress appeared first on Lee Willis.

]]>
I’m the maintainer of a reasonably well-used WooCommerce plugin that currently generates a full set of product data from a store This is currently done on-demand to make sure the information is up to date. On smallish stores, everything works just fine. It’s even OK on larger stores as long as your hosting is ‘modern’ (think reasonable PHP versions, execution limits, persistent object cache etc.).

However, some client hosting can’t always manage to pull products, build product objects, apply business logic for output, and construct the output for all products within execution time limits / memory limits. This is especially the case for stores which may have large inventories, but not necessarily high levels of site traffic. These people have had to make do with generating multiple, partial feeds which increases complexity for them, and can cause other issues around re-use of output data with multiple integration partners.

There’s a couple of obvious approaches to solving this:

  1. Make the processing less complex
  2. General code optimisations
  3. Pre-generate the output and cache it

I’ve looked at, and worked on, several of these avenues over the years, [1] and [2] have given me some pretty good results, and even proved a learning opportunity in WordPress internals at times…

https://twitter.com/leewillis77/status/768859124339736577

It’s now reached the point that the only way to eek out more performance would be to stop using WordPress to generate the content, and to pull it out with straight database queries instead. This would no doubt be a lot quicker, and a lot lighter on CPU.

However, it misses out on a lot of the point of WordPress – that plugins can add, update, and remove information programatically.

From my support work on the plugin over the years, it’s clear that many people rely on plugins / hook customisations to get their final data to be what they want. Raw SQL queries would most likely result in incorrect data, so it’s not really an option.

That leaves us with item [3] – pre-generating the output and caching it. Due to the previous scalability concerns though – we can’t assume that we can generate the full output in a single request. Nor do we want to have to invalidate the full output if a single product, or category is changed.

The solution I’ve settled on generates cached output for each item included in the full output. This gives a couple of benefits:

  1. We can generate our final output with a simple SQL query to pull all of the fragments. This is quick. We also don’t have to  worry that information won’t include input from other plugins on the site as full processing was used to build the fragment
  2. We can invalidate, and rebuild single products, or sets of products without having to invalidate everything
  3. We can build up our cached output in parts, we don’t have to generate it all at once

I was left with a requirement for background processing infrastructure that the pre-generation, and batched invalidation could be handed off to.

I’ve been working a lot with Laravel recently. One of its strengths, and something I’ve used on most (if not all) of my Laravel projects is its Queue implementation. It allows you to easily add jobs to one or more queues, and have them processed by workers in the background. You can set up multiple queues, and you’re in control of how many workers you set up, and which queues they’ll process. The library is usable standalone – it can be used outside of a Laravel project. Unfortunately this plugin supports WordPress’ minimum requirements which are still anchored at PHP 5.2, while Laravel’s Queue system requires 5.6.4 minimum making it a non-starter.

Fortunately, I came across and mentally noted the WP Background Processing library from Ashley Rich / Delicious Brains a while ago:

It’s the perfect solution to this problem. It’s simple, and lets you build background jobs that will run automatically through WordPress’ existing cron infrastructure, taking care to balance running as many jobs as possible in an execution with getting through the jobs as quickly as possible. It’s also compatible with PHP 5.2.

Using the library has let me build out some pretty neat invalidation / pre-generation jobs without having to worry about putting together the cron logic myself. Definitely worth looking at if you need to do any background processing in WordPress plugins.

  1. Stuff I’ve used
  2. Error tracking with Sentry
  3. Autotrack for Google Analytics
  4. WordPress performance tracking with Time-stack
  5. Enforce user password strength
  6. WYSIWYG with Summernote
  7. Backing up your Laravel app
  8. Adding Google Maps to your Laravel application
  9. Activity logging in Laravel
  10. Image handling in PHP with Intervention Image
  11. Testing Laravel emails with MailThief
  12. Assessing software health
  13. IP Geolocation with MaxMind’s GeoLite2
  14. Uptime monitoring with Uptime Robot
  15. Product tours with Hopscotch
  16. Background processing for WordPress
  17. Using oEmbed resources in Laravel

The post Background processing for WordPress appeared first on Lee Willis.

]]>
https://www.leewillis.co.uk/background-processing-wordpress/feed/ 0
Custom model events with Laravel 5.4 https://www.leewillis.co.uk/custom-model-events-laravel/ https://www.leewillis.co.uk/custom-model-events-laravel/#comments Tue, 07 Mar 2017 13:46:42 +0000 https://www.leewillis.co.uk/?p=936 Laravel’s eloquent ORM has a nice system for tracking, and responding to events on models. This allows you to create an Observer class that handles code that should run when various actions are performed on a model. There are a … Continue reading

The post Custom model events with Laravel 5.4 appeared first on Lee Willis.

]]>
Laravel’s eloquent ORM has a nice system for tracking, and responding to events on models. This allows you to create an Observer class that handles code that should run when various actions are performed on a model. There are a set of standard events (created, updated, deleted etc.) that can be used to achieve many things. These can be useful if you need to send notifications when a new model is created, or update something when a model is updated.

However, as your models get more complex, you may find yourself needing different events. Imagine you have a content model which has statuses, for example draft, pending review, and published. If you want to perform different actions based on the model status then you can attach an observer to the model, and listed for the created / updated events.

You can then check the new status and fire off the relevant code. This can get messy though, and also doesn’t reflect what happened to the model to move it into it’s current status. For example, is the content in “pending review” because it’s a draft that someone wants to publish, or an article that was published but has been bumped back down for review? The current model status doesn’t tell you that.

Now, you can create your own events in Laravel, and fire them off, however that would mean you have some event listeners in your model observer, and some in a bespoke event listener. Messy.

It’s nicer to be able to handle everything the same way. Fortunately Eloquent’s model event system can be extended to support custom events which you can fire at the appropriate point.

To add a new event, simply set the $observables property on your model.

<?php

use Illuminate\Database\Eloquent\Model;

class MyContentModel extends Model
{
  /**
   * Additional observable events.
   */
  protected $observables = [
    'sentforreview',
    'rejected',
  ];
}

This tells Laravel that there are two new model events that an observer can listen for. In our observer, we can listed to these by defining the appropriate function as we would with any of the standard events:

<?php

namespace App\Observers;

class MyContentObserver
{

  public function sentforreview(MyContent $myContent)
  {
    // Your logic here.
  }

  public function rejected(MyContent $myContent)
  {
    // Your logic here.
  }

}

So far, so good. We have defined our custom observables, and built a method to listed for them. However – the event will never be fired. After all, Laravel doesn’t know when it should be fired. Firing the event is simple though. Within your model you simply call fireModelEvent() and tell it the event you are firing, for example:

<?php

use Illuminate\Database\Eloquent\Model;

class MyContentModel extends Model
{
  public function sendForReview()
  {
     // Do any other updates to the model here.
     // Then fire the event.
     $this->fireModelEvent('sentforreview', false);
  }

  public function reject()
  {
     // Do any other updates to the model here.
     // Then fire the event.
     $this->fireModelEvent('rejected', false);
  }
}

Now, you can have a single model observer that handles standard, and custom events keeping everything nice and tidy.

The post Custom model events with Laravel 5.4 appeared first on Lee Willis.

]]>
https://www.leewillis.co.uk/custom-model-events-laravel/feed/ 4
IP Geolocation with MaxMind’s GeoLite2 https://www.leewillis.co.uk/ip-geolocation-maxminds-geolite2/ https://www.leewillis.co.uk/ip-geolocation-maxminds-geolite2/#respond Tue, 15 Nov 2016 19:45:14 +0000 http://www.leewillis.co.uk/?p=910 IP geolocation is something that’s needed more and more as people publish & trade internationally. Stores want to offer different pricing, currencies, shipping rules to different countries, or provide content in different languages. Many systems have something already baked in, … Continue reading

The post IP Geolocation with MaxMind’s GeoLite2 appeared first on Lee Willis.

]]>
IP geolocation is something that’s needed more and more as people publish & trade internationally. Stores want to offer different pricing, currencies, shipping rules to different countries, or provide content in different languages.

Many systems have something already baked in, but working on a project recently I needed to do some simple country-level IP geolocation. My previous iteration had used a third party service, but that slowed things down, and had a tendency to be unreliable – recently going AWOL for a couple of weeks!

There are some free GeoLocation databases provided by MaxMind, but I doubt I’m telling you anything new there, it seems to be fairly well known about. However I’ve never actually used them myself directly, so in I dived.

Firstly I used their public PHP wrapper:

I was able to pull it into my project using Composer really easily, download the database and hook it up simply. Running a geolocation really was as simple as their documentation suggested, I ended up with this in my code:

$reader = new GeoIp2\Database\Reader( GEOIP_DB_PATH );
$record = $reader->country( $this->get_user_ip() );
$country = $record->country->isoCode;

Really nice and simple, and a lot more reliable than my previous solution, and definitely something I’d use again in the future without hesitation.

Image credit: https://commons.wikimedia.org/wiki/File:Red1234.jpg

  1. Stuff I’ve used
  2. Error tracking with Sentry
  3. Autotrack for Google Analytics
  4. WordPress performance tracking with Time-stack
  5. Enforce user password strength
  6. WYSIWYG with Summernote
  7. Backing up your Laravel app
  8. Adding Google Maps to your Laravel application
  9. Activity logging in Laravel
  10. Image handling in PHP with Intervention Image
  11. Testing Laravel emails with MailThief
  12. Assessing software health
  13. IP Geolocation with MaxMind’s GeoLite2
  14. Uptime monitoring with Uptime Robot
  15. Product tours with Hopscotch
  16. Background processing for WordPress
  17. Using oEmbed resources in Laravel

The post IP Geolocation with MaxMind’s GeoLite2 appeared first on Lee Willis.

]]>
https://www.leewillis.co.uk/ip-geolocation-maxminds-geolite2/feed/ 0
Image handling in PHP with Intervention Image https://www.leewillis.co.uk/image-handling-php-intervention-image/ https://www.leewillis.co.uk/image-handling-php-intervention-image/#respond Thu, 27 Oct 2016 11:00:42 +0000 http://www.leewillis.co.uk/?p=793 If you’ve done much with PHP you’ve probably come across its image handling libraries. Normally this involves using either the GD, or ImageMagick. These work reasonably well, but there are a number of disadvantages: The APIs are thin wrappers around the … Continue reading

The post Image handling in PHP with Intervention Image appeared first on Lee Willis.

]]>
If you’ve done much with PHP you’ve probably come across its image handling libraries. Normally this involves using either the GD, or ImageMagick.

These work reasonably well, but there are a number of disadvantages:

  1. The APIs are thin wrappers around the relevant image libraries. Neither of them offer particularly developer-friendly APIs, and the two APIs aren’t equal enough to make switching between them simple.
  2. You have to know which library your server has in order to start developing, or make extra work, and support both.

On a recent project I needed to do image manipulation (thumbnail generation etc.), and came across the Intervention Image library. This is a PHP library that can be used in any PHP project, and offers a much improved API for working with images. The API is agnostic to whether you’re using ImageMagick, or GD, so you can swap between them at will without having to re-code your application.

Next time you’re working with images, check out Intervention Image.

 

 

  1. Stuff I’ve used
  2. Error tracking with Sentry
  3. Autotrack for Google Analytics
  4. WordPress performance tracking with Time-stack
  5. Enforce user password strength
  6. WYSIWYG with Summernote
  7. Backing up your Laravel app
  8. Adding Google Maps to your Laravel application
  9. Activity logging in Laravel
  10. Image handling in PHP with Intervention Image
  11. Testing Laravel emails with MailThief
  12. Assessing software health
  13. IP Geolocation with MaxMind’s GeoLite2
  14. Uptime monitoring with Uptime Robot
  15. Product tours with Hopscotch
  16. Background processing for WordPress
  17. Using oEmbed resources in Laravel

The post Image handling in PHP with Intervention Image appeared first on Lee Willis.

]]>
https://www.leewillis.co.uk/image-handling-php-intervention-image/feed/ 0