Skip to content

WheelSize Client Library

Overview

Standalone PHP client for the WheelSize.com API. Provides global vehicle database with comprehensive wheel and tyre fitment data.

Package: atraxion/wheelsize-client

Installation

composer require atraxion/wheelsize-client

Configuration

use Atraxion\WheelSize\Config;
use Atraxion\WheelSize\WheelSizeClient;

$config = new Config(
    apiKey: 'your-api-key',
    baseUrl: 'https://api.wheel-size.com/v2',
    region: 'eu', // 'eu', 'us', 'global'
    timeout: 30
);

$client = new WheelSizeClient($config);

Core Features

Get All Makes

$makes = $client->getMakes();

foreach ($makes as $make) {
    echo $make->getSlug();  // "volkswagen"
    echo $make->getName();  // "Volkswagen"
}

Get Models

$models = $client->getModels('volkswagen');

foreach ($models as $model) {
    echo $model->getSlug();       // "golf"
    echo $model->getName();       // "Golf"
    echo $model->getYearFrom();   // 1974
    echo $model->getYearTo();     // null
}

Get Years for Model

$years = $client->getYears('volkswagen', 'golf');

foreach ($years as $year) {
    echo $year->getYear();        // 2023
    echo $year->getGeneration();  // "Golf 8 (CD)"
}

Get Modifications (Variants)

$modifications = $client->getModifications('volkswagen', 'golf', 2023);

foreach ($modifications as $mod) {
    echo $mod->getSlug();        // "2-0-tdi-150hp"
    echo $mod->getName();        // "2.0 TDI 150hp"
    echo $mod->getEngineType();  // "diesel"
    echo $mod->getPower();       // 150
    echo $mod->getTrim();        // "Style"
}

Get Vehicle Wheels/Tyres

$vehicle = $client->getVehicle('volkswagen', 'golf', 2023, '2-0-tdi-150hp');

// Technical specifications
echo $vehicle->getBoltPattern();     // "5x112"
echo $vehicle->getCenterBore();      // 57.1
echo $vehicle->getStud();            // "M14x1.5"
echo $vehicle->getRimDiameter();     // 17

// Wheel options
foreach ($vehicle->getWheels() as $wheel) {
    // Front wheel
    echo $wheel->getFront()->getRimDiameter();   // 17
    echo $wheel->getFront()->getRimWidth();      // 7.5
    echo $wheel->getFront()->getRimOffset();     // 41
    echo $wheel->getFront()->getTireWidth();     // 225
    echo $wheel->getFront()->getTireAspect();    // 45
    echo $wheel->getFront()->getTireType();      // "R" (radial)

    // Rear wheel (may differ for staggered)
    if ($wheel->getRear()) {
        echo $wheel->getRear()->getRimDiameter();
    }

    // Is this OE?
    echo $wheel->isStock() ? 'Original' : 'Optional';
}

Search by Tyre Size

$vehicles = $client->searchByTyreSize(225, 45, 17);

foreach ($vehicles as $vehicle) {
    echo $vehicle->getMake();
    echo $vehicle->getModel();
    echo $vehicle->getYear();
}

Search by Wheel Size

$vehicles = $client->searchByWheelSize(
    diameter: 17,
    width: 7.5,
    pcd: '5x112',
    offset: 41
);

Models

Vehicle

readonly class Vehicle
{
    public function __construct(
        public string $make,
        public string $makeName,
        public string $model,
        public string $modelName,
        public int $year,
        public ?string $modification,
        public string $generation,
        public TechnicalSpecs $specs,
        /** @var WheelSetup[] */
        public array $wheels
    ) {}
}

TechnicalSpecs

readonly class TechnicalSpecs
{
    public function __construct(
        public string $boltPattern,     // "5x112"
        public float $centerBore,       // 57.1
        public string $stud,            // "M14x1.5"
        public int $bolts,              // 5
        public float $pcd,              // 112
        public ?string $threadType,     // "bolt" or "nut"
        public ?float $hubDiameter,
        public ?string $trimLevel
    ) {}

    public function getPcdParts(): array
    {
        return [
            'bolts' => $this->bolts,
            'circle' => $this->pcd,
        ];
    }
}

WheelSetup

readonly class WheelSetup
{
    public function __construct(
        public WheelPosition $front,
        public ?WheelPosition $rear,  // null if same as front
        public bool $isStock,
        public ?string $pressureFront,
        public ?string $pressureRear
    ) {}

    public function isStaggered(): bool
    {
        return $this->rear !== null;
    }
}

WheelPosition

readonly class WheelPosition
{
    public function __construct(
        public float $rimDiameter,    // 17
        public float $rimWidth,       // 7.5
        public int $rimOffset,        // 41
        public int $tireWidth,        // 225
        public int $tireAspect,       // 45
        public string $tireType,      // "R"
        public ?string $loadIndex,    // "94"
        public ?string $speedIndex    // "V"
    ) {}

    public function getTyreSize(): string
    {
        return sprintf(
            '%d/%d%s%.0f',
            $this->tireWidth,
            $this->tireAspect,
            $this->tireType,
            $this->rimDiameter
        );
    }

    public function getFullTyreSize(): string
    {
        $size = $this->getTyreSize();
        if ($this->loadIndex && $this->speedIndex) {
            $size .= " {$this->loadIndex}{$this->speedIndex}";
        }
        return $size;
    }

    public function getWheelSize(): string
    {
        return sprintf('%.0fx%.1f ET%d', $this->rimDiameter, $this->rimWidth, $this->rimOffset);
    }
}

Adapting to Common Interface

use Atraxion\VehicleData\VehicleDataAdapterInterface;
use Atraxion\VehicleData\Model\VehicleFitment;
use Atraxion\VehicleData\Model\TyreSize;
use Atraxion\VehicleData\Model\WheelSpec;

class WheelSizeAdapter implements VehicleDataAdapterInterface
{
    public function __construct(
        private WheelSizeClient $client
    ) {}

    public function getFitments(string $variantExternalId): VehicleFitment
    {
        // Parse external ID: "volkswagen/golf/2023/2-0-tdi-150hp"
        [$make, $model, $year, $modification] = explode('/', $variantExternalId);

        $vehicle = $this->client->getVehicle($make, $model, (int) $year, $modification);

        $tyreSizes = [];
        $wheelSpecs = [];

        foreach ($vehicle->wheels as $wheel) {
            // Add front tyre size
            $tyreSizes[] = new TyreSize(
                width: $wheel->front->tireWidth,
                aspectRatio: $wheel->front->tireAspect,
                diameter: $wheel->front->rimDiameter,
                position: $wheel->isStaggered() ? 'front' : 'both',
                isOriginalEquipment: $wheel->isStock
            );

            // Add rear if different
            if ($wheel->isStaggered()) {
                $tyreSizes[] = new TyreSize(
                    width: $wheel->rear->tireWidth,
                    aspectRatio: $wheel->rear->tireAspect,
                    diameter: $wheel->rear->rimDiameter,
                    position: 'rear',
                    isOriginalEquipment: $wheel->isStock
                );
            }

            // Add wheel spec
            $wheelSpecs[] = new WheelSpec(
                diameter: $wheel->front->rimDiameter,
                width: $wheel->front->rimWidth,
                pcd: $vehicle->specs->boltPattern,
                centerBore: $vehicle->specs->centerBore,
                offsetMin: $wheel->front->rimOffset - 5,
                offsetMax: $wheel->front->rimOffset + 10
            );
        }

        return new VehicleFitment(
            tyreSizes: array_unique($tyreSizes, SORT_REGULAR),
            wheelSpecs: array_unique($wheelSpecs, SORT_REGULAR),
            originalEquipment: $this->extractOeData($vehicle)
        );
    }

    public function lookupByPlate(string $plate, string $country): ?VehicleIdentification
    {
        // WheelSize does not support plate lookup
        return null;
    }

    public function getSourceId(): string
    {
        return 'wheelsize';
    }
}

Error Handling

use Atraxion\WheelSize\Exception\ApiException;
use Atraxion\WheelSize\Exception\NotFoundException;
use Atraxion\WheelSize\Exception\QuotaExceededException;

try {
    $vehicle = $client->getVehicle($make, $model, $year, $mod);
} catch (NotFoundException $e) {
    // Vehicle not found
} catch (QuotaExceededException $e) {
    // API quota exceeded
    $resetTime = $e->getResetTime();
} catch (ApiException $e) {
    $this->logger->error('WheelSize error', ['error' => $e->getMessage()]);
}

Gherkin Scenarios

Feature: WheelSize Client
  As a developer
  I want to access WheelSize vehicle database
  Using a clean client library

  Scenario: Browse vehicle catalog
    When I request all makes
    Then I should receive list of manufacturers
    And each make should have slug and name

  Scenario: Get vehicle wheel options
    Given vehicle "VW Golf 2023 2.0 TDI"
    When I request wheel data
    Then I should receive bolt pattern
    And I should receive wheel/tyre combinations

  Scenario: Identify staggered fitment
    Given vehicle with different front and rear
    When I request wheel data
    Then front and rear should have different sizes
    And isStaggered() should return true

  Scenario: Search vehicles by tyre size
    Given tyre size 225/45R17
    When I search compatible vehicles
    Then I should receive list of vehicles
    And all vehicles should accept this size

  Scenario: API quota exceeded
    Given API quota is exhausted
    When I make a request
    Then QuotaExceededException should be thrown
    And reset time should be provided

Configuration Reference

Parameter Type Required Default Description
apiKey string Yes - WheelSize API key
baseUrl string No production API base URL
region string No global Market filter: eu, us, global
timeout int No 30 Request timeout in seconds

API Endpoints Used

Endpoint Method Purpose
/makes GET List all makes
/makes/{make}/models GET List models for make
/makes/{make}/models/{model}/years GET List years for model
/makes/{make}/models/{model}/years/{year}/modifications GET List variants
/makes/{make}/models/{model}/years/{year}/modifications/{mod} GET Get vehicle data
/search/by_tire GET Search by tyre size
/search/by_rim GET Search by wheel size