I prefer to use SVGs whenever possible instead of pngs or font icons. They can be resized, they can be colored, and they’re relatively small. But I also have a set of 700 icons I use and I don’t want to have to copy them to every single site. Instead, I’d like to have them all on a central repository and call them remotely.

To The Cloud

You can use S3 or really anything for this, but I chose DreamObjects since it’s open source and I work for DreamHost.

For this to work, you create a bucket in DreamObjects with whatever name you want. I tend to name them after the website I’m working on, but in this case I’m making what is essentially a media library so a better bucket name would be the service. Keep in mind, while you can make a DNS alias like media.mydomain.com for this, you cannot use that with https at this time. Sucks. I know.

On DreamObjects, the accessible URL will be BUCKET.objects-us-east-1.dream.io — hang on to that. We’ll need it in a bit.

Upload Your Files

Since I plan to use this as a collective for ‘media’ related to a network of sites, I named the bucket for the network and then made subfolders:

  • backups
  • site1
  • site2
  • svg
  • svgcolor

Backups is for everything you’re thinking. Site1 and Site2 are special folders for files unique to those domains only. Think large videos or a podcast. Since they’re not updated a lot, and I want them accessible without draining my server resources, the cloud is perfect. I separated my SVG files into two reasonable folders, because I plan to generate a list of these later.

Calling An Individual File

This is the much easier part. In general, PHP can use file_get_contents() for this. But we’re on WordPress and there is a more reliable way about this.

$svg = wp_remote_get( 'https://BUCKET.objects-us-east-1.dream.io/svg/ICON.svg' );
if ( $svg['response']['code'] !== '404' ) {
	$icon = $svg['body'];
}

By using wp_remote_get it’s possible to check if the file exists before displaying the content of the body. Which is, indeed, how one displays the content.

The reason, by the way, we want to use wp_remote_get and not file_get_contents is that there’s no way to check if the file exists with the latter. You could still use file_get_contents to display the file, but once you’ve done the remote get, you may as well use it.

Getting a List Of All SVGs

I’d done this before with local images, getting a list of all the SVGs. You can’t do a foreach of a remote folder like that. So this is a little messier. You’ll need the Amazon AWS SDK for PHP for this. I’ve tested this on the latest of the 2 branch – 2.8.31 – and the 3 branch – 3.32.3 and the code is different but can work.

In both cases, I downloaded the .phar file and included it in a function that I used to save a file with a list of the image names in them. By doing that, I can have other functions call the file and not have to query DreamObjects every time I want to get a list.

function get_icons() {
	include_once( dirname( __FILE__ ) . '/aws.phar' );

	$svgicons = '';

	// AWS SDK Code Goes Here

	$upload_dir = wp_upload_dir();
	$this_file  = $upload_dir['basedir'] . '/svgicons.txt';
	$open_file  = fopen( $this_file, 'wa+' );
	$write_file = fputs( $open_file, $svgicons );
	fclose( $open_file );
}

I left out the SDK code. Let’s do that now.

SDK V2

The V2 is actually what’s still officially supported by CEPH, but the PHAR file is larger.

	Version 2
	$client = Aws\S3\S3Client::factory(array(
		'base_url' => 'https://objects-us-east-1.dream.io',
		'key'      => AWS_ACCESS_KEY_ID,
		'secret'   => AWS_SECRET_ACCESS_KEY,
		'version' => 'latest',
		'region'  => 'us-east-1',
	));

	$files = $client->getIterator( 'ListObjects', array(
		'Bucket' => 'BUCKET',
		'Prefix' => 'svg/',
	));


	foreach ( $files as $file ) {
		if ( strpos( $file['Key'], '.svg' ) !== false ) {
			$name         = strtolower( substr( $file['Key'] , 0, strrpos( $file['Key'] , ".") ) );
			$name         = str_replace( 'svg/', '', $name );
			$symbolicons .= "$name\r\n";
		}
	}

SDK V3

I would recommend using V3 if possible. Since you’re only using it to get data and not write, it’s fine to use, even if it’s not supported.

	// Version 3
	$s3 = new Aws\S3\S3Client([
		'version' => 'latest',
		'region'  => 'us-east-1',
		'endpoint' => 'https://objects-us-east-1.dream.io',
		'credentials' => [
			'key'    => AWS_ACCESS_KEY_ID,
			'secret' => AWS_SECRET_ACCESS_KEY,
		]
	]);

	$files = $s3->getPaginator( 'ListObjects', [
		'Bucket' => 'BUCKET',
		'Prefix' => 'svg/',
	]);

	foreach ( $files as $file ) {
		foreach ( $file['Contents'] as $item ) {
	
			if ( strpos( $item['Key'], '.svg' ) !== false ) {
				$name = strtolower( substr( $item['Key'] , 0, strrpos( $item['Key'] , ".") ) );
				$name = str_replace( 'svg/', '', $name );
				$symbolicons .= "$name\r\n";
			}
		}
	}

Side Note…

If you’re on DreamHost, you’ll want to add this to your phprc file:

extension=phar.so
detect_unicode = Off
phar.readonly = Off
phar.require_hash = Off
suhosin.executor.include.whitelist = phar

That way it knows to run phar files properly. And by the way, that’s part of why phar files aren’t allowed in your WordPress plugins.

Which is Better?

That’s a difficult question. When it comes to loading them on the front end, it makes little difference. And having them on a CDN or a cloud service is generally better. It also means I don’t have to push the same 400 or so files to multiple servers. On the other hand, calling files from yet another domain gets you a down check on most site speed checks… But the joke’s on them. The image is loaded in PHP.

Of course the massive downside is that if the cloud is down my site can be kinda jacked. But that’s why using a check on the response code is your lifeline.

Reader Interactions

%d bloggers like this: