Skip to main content

Examples & Use Cases

Real-world examples and practical implementations using the Trading Card API PHP SDK.

Card Price Tracker

Track price changes for specific cards over time.

<?php

namespace App\Services;

use CardTechie\TradingCardApiSdk\Facades\TradingCardApiSdk;
use CardTechie\TradingCardApiSdk\Exceptions\{CardNotFoundException, TradingCardApiException};
use Illuminate\Support\Facades\{Cache, Log};

class CardPriceTracker
{
public function trackCard(string $cardId): array
{
try {
// Get card with price data
$cardData = TradingCardApiSdk::card()->get($cardId, [
'include' => 'prices,set,player'
]);

$currentPrice = $this->getCurrentPrice($cardData['prices'] ?? []);

return [
'success' => true,
'card' => $cardData,
'current_price' => $currentPrice,
'price_trend' => $this->calculatePriceTrend($cardId, $currentPrice)
];

} catch (CardNotFoundException $e) {
Log::warning("Card not found for tracking", ['card_id' => $cardId]);
return ['success' => false, 'error' => 'Card not found'];
} catch (TradingCardApiException $e) {
Log::error("API error while tracking card", [
'card_id' => $cardId,
'error' => $e->getMessage()
]);
return ['success' => false, 'error' => 'API error'];
}
}

private function getCurrentPrice(array $prices): ?float
{
if (empty($prices)) {
return null;
}

// Sort by date and get most recent
usort($prices, fn($a, $b) =>
strtotime($b['date']) <=> strtotime($a['date'])
);

return (float) $prices[0]['price'];
}

private function calculatePriceTrend(string $cardId, ?float $currentPrice): array
{
$previousPrice = Cache::get("price_history_{$cardId}");

if (!$previousPrice || !$currentPrice) {
return ['trend' => 'insufficient_data'];
}

$change = $currentPrice - $previousPrice;
$percentageChange = ($change / $previousPrice) * 100;

// Store current price for next comparison
Cache::put("price_history_{$cardId}", $currentPrice, now()->addDay());

return [
'previous_price' => $previousPrice,
'current_price' => $currentPrice,
'change' => round($change, 2),
'percentage_change' => round($percentageChange, 2),
'trend' => $change > 0 ? 'increasing' : 'decreasing'
];
}
}

// Usage
$tracker = new CardPriceTracker();
$result = $tracker->trackCard('card-123');

if ($result['success']) {
echo "Card: " . $result['card']['name'] . "\n";
echo "Current Price: $" . $result['current_price'] . "\n";
echo "Trend: " . $result['price_trend']['trend'] . "\n";
}

Collection Manager

Manage card collections with valuation and completion tracking.

<?php

namespace App\Services;

use CardTechie\TradingCardApiSdk\Facades\TradingCardApiSdk;
use CardTechie\TradingCardApiSdk\Exceptions\TradingCardApiException;
use App\Models\{Collection, CollectionCard};

class CollectionManager
{
public function addCardToCollection(Collection $collection, string $cardId, array $metadata = []): array
{
try {
// Get card data from API
$cardData = TradingCardApiSdk::card()->get($cardId, [
'include' => 'set,player,prices'
]);

// Check if card already exists in collection
$existingCard = $collection->cards()
->where('api_card_id', $cardId)
->first();

if ($existingCard) {
// Update quantity if card already exists
$existingCard->increment('quantity', $metadata['quantity'] ?? 1);

return [
'success' => true,
'action' => 'updated',
'card' => $existingCard
];
}

// Add new card to collection
$collectionCard = $collection->cards()->create([
'api_card_id' => $cardId,
'name' => $cardData['name'],
'set_name' => $cardData['set']['name'] ?? null,
'player_name' => $cardData['player']['name'] ?? null,
'quantity' => $metadata['quantity'] ?? 1,
'condition' => $metadata['condition'] ?? 'near_mint',
'purchase_price' => $metadata['purchase_price'] ?? null,
'current_price' => $this->getCurrentPrice($cardData['prices'] ?? []),
'notes' => $metadata['notes'] ?? null
]);

return [
'success' => true,
'action' => 'added',
'card' => $collectionCard
];

} catch (TradingCardApiException $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}

public function calculateCollectionValue(Collection $collection): array
{
$cards = $collection->cards()->get();
$totalValue = 0;
$totalPurchasePrice = 0;

foreach ($cards as $card) {
$cardValue = ($card->current_price ?? 0) * $card->quantity;
$totalValue += $cardValue;

if ($card->purchase_price) {
$totalPurchasePrice += $card->purchase_price * $card->quantity;
}
}

$profitLoss = $totalPurchasePrice > 0 ? $totalValue - $totalPurchasePrice : 0;

return [
'total_cards' => $cards->sum('quantity'),
'unique_cards' => $cards->count(),
'total_value' => round($totalValue, 2),
'total_purchase_price' => round($totalPurchasePrice, 2),
'profit_loss' => round($profitLoss, 2)
];
}

private function getCurrentPrice(array $prices): ?float
{
if (empty($prices)) {
return null;
}

usort($prices, fn($a, $b) =>
strtotime($b['date']) <=> strtotime($a['date'])
);

return (float) $prices[0]['price'];
}
}

// Usage
$manager = new CollectionManager();

// Add card to collection
$result = $manager->addCardToCollection($collection, 'card-123', [
'quantity' => 2,
'condition' => 'near_mint',
'purchase_price' => 15.99,
'notes' => 'Bought at local card shop'
]);

// Calculate collection value
$value = $manager->calculateCollectionValue($collection);
echo "Collection worth: $" . number_format($value['total_value'], 2);

Laravel Controllers

Integrate SDK into Laravel controllers for web applications.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use CardTechie\TradingCardApiSdk\Facades\TradingCardApiSdk;
use CardTechie\TradingCardApiSdk\Exceptions\{
CardNotFoundException,
ValidationException,
TradingCardApiException
};

class CardController extends Controller
{
public function index(Request $request)
{
try {
$cards = TradingCardApiSdk::card()->getList([
'page' => $request->get('page', 1),
'limit' => 25,
'name' => $request->get('search'),
'genre' => $request->get('genre'),
'year' => $request->get('year')
]);

return view('cards.index', [
'cards' => $cards['data'] ?? [],
'pagination' => $cards['meta'] ?? [],
'filters' => $request->only(['search', 'genre', 'year'])
]);

} catch (TradingCardApiException $e) {
return back()->withError('Unable to load cards. Please try again.');
}
}

public function show($id)
{
try {
$card = TradingCardApiSdk::card()->get($id, [
'include' => 'set,player,team,prices'
]);

return view('cards.show', compact('card'));

} catch (CardNotFoundException $e) {
abort(404, 'Card not found');
} catch (TradingCardApiException $e) {
return back()->withError('Unable to load card details.');
}
}

public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'set_id' => 'required|string',
'player_id' => 'nullable|string',
'condition' => 'required|string|in:mint,near_mint,excellent,good,fair,poor'
]);

try {
$card = TradingCardApiSdk::card()->create($request->all());

return redirect()->route('cards.show', $card['id'])
->with('success', 'Card created successfully!');

} catch (ValidationException $e) {
return back()
->withErrors($e->getValidationErrors())
->withInput();
} catch (TradingCardApiException $e) {
return back()
->withError('Failed to create card. Please try again.')
->withInput();
}
}
}

Artisan Commands

Create CLI commands for batch operations and maintenance tasks.

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use CardTechie\TradingCardApiSdk\Facades\TradingCardApiSdk;
use CardTechie\TradingCardApiSdk\Exceptions\TradingCardApiException;

class SyncCardsCommand extends Command
{
protected $signature = 'cards:sync {--limit=100 : Number of cards to sync} {--genre= : Filter by genre}';
protected $description = 'Sync cards from Trading Card API';

public function handle()
{
$this->info('Starting card synchronization...');

$limit = (int) $this->option('limit');
$genre = $this->option('genre');

$filters = ['limit' => $limit];
if ($genre) {
$filters['genre'] = $genre;
}

try {
$response = TradingCardApiSdk::card()->getList($filters);
$cards = $response['data'] ?? [];

$this->output->progressStart(count($cards));

foreach ($cards as $cardData) {
// Process each card (store in database, update cache, etc.)
$this->processCard($cardData);
$this->output->progressAdvance();

// Small delay to respect rate limits
usleep(50000); // 50ms
}

$this->output->progressFinish();
$this->info('Card synchronization completed!');
$this->line("Processed " . count($cards) . " cards");

} catch (TradingCardApiException $e) {
$this->error('Synchronization failed: ' . $e->getMessage());
return Command::FAILURE;
}

return Command::SUCCESS;
}

private function processCard(array $cardData): void
{
// Implementation depends on your needs
// This could update a local database, cache, search index, etc.
$this->line("Processing: {$cardData['name']}");
}
}

Queue Jobs

Handle API operations asynchronously using Laravel's queue system.

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use CardTechie\TradingCardApiSdk\Facades\TradingCardApiSdk;
use CardTechie\TradingCardApiSdk\Exceptions\TradingCardApiException;
use App\Models\User;
use App\Notifications\PriceAlertNotification;

class ProcessPriceAlertJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

public function __construct(
private string $cardId,
private User $user,
private float $targetPrice
) {}

public function handle()
{
try {
$card = TradingCardApiSdk::card()->get($this->cardId, [
'include' => 'prices'
]);

$currentPrice = $this->getCurrentPrice($card['prices'] ?? []);

if ($currentPrice && $currentPrice <= $this->targetPrice) {
// Price target reached, send notification
$this->user->notify(new PriceAlertNotification([
'card' => $card,
'current_price' => $currentPrice,
'target_price' => $this->targetPrice
]));
}

} catch (TradingCardApiException $e) {
// Log error and potentially retry
\Log::error('Price alert job failed', [
'card_id' => $this->cardId,
'user_id' => $this->user->id,
'error' => $e->getMessage()
]);

// Retry the job if it's a temporary error
if ($e instanceof RateLimitException) {
$this->release($e->getRetryAfter());
}
}
}

private function getCurrentPrice(array $prices): ?float
{
if (empty($prices)) {
return null;
}

usort($prices, fn($a, $b) =>
strtotime($b['date']) <=> strtotime($a['date'])
);

return (float) $prices[0]['price'];
}
}

// Dispatch the job
ProcessPriceAlertJob::dispatch($cardId, $user, $targetPrice);

API Resource Integration

Create Laravel API resources for consistent response formatting.

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class CardResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->resource['id'],
'name' => $this->resource['name'],
'description' => $this->resource['description'] ?? null,
'condition' => $this->resource['condition'] ?? 'unknown',
'rarity' => $this->resource['rarity'] ?? 'common',
'set' => $this->when(
isset($this->resource['set']),
fn() => new SetResource($this->resource['set'])
),
'player' => $this->when(
isset($this->resource['player']),
fn() => new PlayerResource($this->resource['player'])
),
'prices' => $this->when(
isset($this->resource['prices']),
fn() => PriceResource::collection($this->resource['prices'])
),
'links' => [
'self' => route('api.cards.show', $this->resource['id']),
'web' => route('cards.show', $this->resource['id'])
]
];
}
}

// API Controller usage
class ApiCardController extends Controller
{
public function show($id)
{
try {
$card = TradingCardApiSdk::card()->get($id, [
'include' => 'set,player,prices'
]);

return new CardResource($card);

} catch (CardNotFoundException $e) {
return response()->json(['error' => 'Card not found'], 404);
} catch (TradingCardApiException $e) {
return response()->json(['error' => 'API error'], 500);
}
}
}

Testing with the SDK

Write tests for your SDK integrations.

<?php

namespace Tests\Feature;

use Tests\TestCase;
use CardTechie\TradingCardApiSdk\Facades\TradingCardApiSdk;
use CardTechie\TradingCardApiSdk\Exceptions\CardNotFoundException;

class CardControllerTest extends TestCase
{
public function test_can_view_card_details()
{
// Mock the SDK response
TradingCardApiSdk::shouldReceive('card->get')
->with('card-123', ['include' => 'set,player,team,prices'])
->andReturn([
'id' => 'card-123',
'name' => 'Test Card',
'description' => 'A test card',
'set' => ['name' => 'Test Set'],
'player' => ['name' => 'Test Player']
]);

$response = $this->get('/cards/card-123');

$response->assertStatus(200);
$response->assertViewIs('cards.show');
$response->assertViewHas('card');
}

public function test_returns_404_for_missing_card()
{
// Mock the SDK to throw an exception
TradingCardApiSdk::shouldReceive('card->get')
->with('invalid-id', ['include' => 'set,player,team,prices'])
->andThrow(new CardNotFoundException('Card not found'));

$response = $this->get('/cards/invalid-id');

$response->assertStatus(404);
}
}

Best Practices

1. Error Handling

Always handle exceptions appropriately:

try {
$card = TradingCardApiSdk::card()->get($id);
} catch (CardNotFoundException $e) {
// Handle not found specifically
} catch (ValidationException $e) {
// Handle validation errors
} catch (TradingCardApiException $e) {
// Handle general API errors
}

2. Rate Limiting

Respect API rate limits:

foreach ($cardIds as $cardId) {
try {
$card = TradingCardApiSdk::card()->get($cardId);
// Process card
} catch (RateLimitException $e) {
sleep($e->getRetryAfter());
// Retry the request
}

// Add small delay between requests
usleep(100000); // 100ms
}

3. Caching

Cache API responses when appropriate:

$cacheKey = "card_{$cardId}";
$card = Cache::remember($cacheKey, 3600, function() use ($cardId) {
return TradingCardApiSdk::card()->get($cardId);
});

4. Logging

Log API interactions for debugging:

try {
$card = TradingCardApiSdk::card()->get($cardId);
Log::info('Card fetched successfully', ['card_id' => $cardId]);
} catch (TradingCardApiException $e) {
Log::error('Card fetch failed', [
'card_id' => $cardId,
'error' => $e->getMessage(),
'request_id' => $e->getRequestId()
]);
}

These examples demonstrate practical, real-world usage patterns for the Trading Card API PHP SDK in Laravel applications. Each example includes proper error handling, follows Laravel conventions, and demonstrates best practices for API integration.