Created
April 6, 2016 17:05
-
-
Save wells/53739a4c9676e22e59821bc420a2b92b to your computer and use it in GitHub Desktop.
API Versioning in Laravel AppServiceProvider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers; | |
use Illuminate\Support\ServiceProvider; | |
class AppServiceProvider extends ServiceProvider | |
{ | |
/** | |
* Bootstrap any application services. | |
* | |
* @return void | |
*/ | |
public function boot() | |
{ | |
// | |
} | |
/** | |
* Register any application services. | |
* | |
* @return void | |
*/ | |
public function register() | |
{ | |
// Bind versioned API resources to their interfaces | |
$namespace = 'Wells\\Project\\'; | |
// These are mere examples | |
$resources = [ | |
'Posts', | |
'Users', | |
]; | |
$services = []; | |
foreach ($resources as $resource) { | |
$services[$namespace.$resource] = | |
$this->mapVersion($namespace, $resource); | |
} | |
foreach ($services as $key => $value) { | |
$this->app->bindIf($key, $value); | |
} | |
} | |
protected function mapVersion($namespace, $resource) | |
{ | |
// Retrieve the Accept header from the Request | |
$mimeType = request()->server('HTTP_ACCEPT', '*/*'); | |
// Try to load the requested version, if provided | |
$version = $this->parseMimeType($mimeType); | |
$classPath = $version ? | |
$this->formatPath($namespace, $version, $resource) : null; | |
// Requested version exists for this resource | |
if ($classPath && class_exists($classPath)) { | |
return $classPath; | |
} | |
// Map the latest version of the resource | |
$versions = (array) config('project.api_versions', [1.0, ]); | |
// Reverse sort of the API versions | |
rsort($versions); | |
// Find the latest version of this resource | |
foreach ($versions as $version) { | |
// Convert to underscore format (i.e. V1, V1_1, etc) | |
$version = $this->formatVersion($version); | |
$classPath = $this->formatPath( | |
$namespace, $version, $resource | |
); | |
if (class_exists($classPath)) { | |
break; | |
} | |
} | |
return $classPath; | |
} | |
protected function parseMimeType($mimeType) | |
{ | |
// Break up the mime type by semicolon | |
$mimeParts = (array) array_filter( | |
explode(';', $mimeType), 'strlen' | |
); | |
foreach ($mimeParts as $part) { | |
if (starts_with(trim($part), 'version=')) { | |
// Remove version= from string | |
$version = str_replace('version=', '', $part); | |
// Convert to underscore format (i.e. V1, V1_1, etc) | |
$version = $this->formatVersion($version); | |
return $version; | |
} | |
} | |
return null; | |
} | |
protected function formatPath($namespace, $version, $resource) { | |
return $namespace.'V'.$version.'\\'.$resource; | |
} | |
protected function formatVersion($version) | |
{ | |
return str_replace('.', '_', (double) $version); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment