One of the things I miss most from my C# coding days is output parameters.
For those of you who haven’t seen them before, output parameters are relatively simple. They’re parameters that you pass in to a function that are modified by the function itself, essentially allowing you to return multiple values from a single function.
I often used these to pass in and return flags relating to the relative success of the internals of a function in C#. Usually, my functions were built in such a way that they always returned a value (usually a fallback), so as to allow the program to continue in the event of remote API failures.
Passing a [cci]flags[/cci] parameter allowed me to programatically check whether or not the API call was successful, which in turn informed how I cached the function’s return value.[ref]In most cases, API failures would be retried on a parallel thread so end users were more likely to see cached data on their second attempt.[/ref]
A WordPress Problem
The other day, I found myself needing a similar feature in a WordPress project. I was building code that would automatically generate a shortlink via a remote API – the problem was the function would be used on front-end requests and needed to always return something useful.
I originally wrote a function very similar to the code below:
function get_shortlink( $post_id ) {
// Get a cached shortlink
$shortlink = get_post_meta( $post_id, 'shortlink', true );
if ( false === $shortlink ) {
$longlink = get_the_permalink( $post_id );
$shortlink = generate_shortlink( $longlink );
// generate_shortlink() will always return a link of some sort, usually
// the full URL if there was a failure.
if ( $shortlink !== $longlink ) {
add_post_meta( $post_id, 'shortlink', $shortlink, true );
}
}
return $shortlink;
}
My issue is that there’s no simple/effective way to tell the difference between a shortened URL and a regular post/page URL.[ref]In the code above, I just assume they’re different. However, you can have minor differences in your links that trigger an in-code inequality but still map to the same path. The project I was working with, for example, was erroneously returning the canonical ([cci]?p=XXX[/cci]) URLs in a [cci]get_the_permalink()[/cci] inside the [cci]get_shortlink()[/cci] function and assuming success. This led to several hundred URLs being inaccurately mapped … a serious issue for the site in question.[/ref] I really wanted to add an output parameter to the function so I could test whether or not it had successfully generated (and cached) the short URL.
So I added one.
Pass by Reference
PHP supports passing parameters by reference. It might not be called an output parameter, but you can fairly easily create something that will serve the same purpose.
My function turned out looking something like:
function generate_shortcode( $longurl, &$created ) {
// Assume failure from the beginning
$created = false;
$path = add_query_arg(
array(
'u' => $longurl,
),
'http://someurlshortener.com'
);
$request = wp_remote_get( $path );
if ( is_wp_error( $request ) ) {
return $longurl;
}
// If not an error, then the URL was shortened.
$created = true;
return wp_remote_retrive_body( $request );
}
And I can invoke it like:
function get_shortlink( $post_id ) {
// Get a cached shortlink
$shortlink = get_post_meta( $post_id, 'shortlink', true );
if ( false === $shortlink ) {
$longlink = get_the_permalink( $post_id );
$shortlink = generate_shortlink( $longlink, $created = false );
// If the flag is true, then the function worked.
if ( $created ) {
add_post_meta( $post_id, 'shortlink', $shortlink, true );
}
}
return $shortlink;
}
After invocation, I can test the value of [cci]$created[/cci] in my other code and immediately know whether or not I should cache the return of the function.
How else might you use output parameters (or an implementation thereof) in your code?