How to Use TOON Format in PHP - Complete Tutorial

Step-by-step guide with code examples to implement TOON in your PHP applications

Published: January 2025 • 12 min read • For PHP Developers

If you're sending data to GPT-4 or Claude and watching your token costs pile up, you're in the right place. TOON format can cut your token usage by about 50% compared to JSON - and it's surprisingly easy to use in PHP.

Whether you're building with Laravel, running vanilla PHP, or working with Symfony, this tutorial walks you through everything step by step. No fancy theory - just practical code you can copy, paste, and actually use. Let's save you some money on those API bills.

What You'll Learn:

  • How to install TOON in your PHP project (takes 2 minutes)
  • Converting your existing PHP arrays to TOON
  • Switching between JSON and TOON whenever you need
  • Using TOON with OpenAI and Claude APIs
  • Laravel-specific tips and tricks
  • A complete real-world example you can steal

What You Need Before Starting

Don't worry - the requirements are pretty basic. If you've built anything in PHP before, you're already good to go:

Your Setup

  • PHP 8.0 or newer (but 7.4 should work too)
  • Composer installed
  • Know what namespaces are (don't need to be an expert)

Your Skills

  • Comfortable writing basic PHP
  • Used arrays and JSON before
  • OpenAI API experience helps, but not required

Step 1: Get TOON Installed (Super Quick)

Installing TOON is dead simple. If you've ever installed a Composer package, you already know how to do this:

1

Regular PHP Project

Just run this in your project folder:

composer require toon-format/toon-php

That's it. No configuration needed.

2

Using Laravel?

Laravel auto-discovers the package, so just install it:

composer require toon-format/toon-php

# Optional: publish the config if you want to customize stuff
php artisan vendor:publish --tag=toon-config
3

Quick Test (Optional)

Want to make sure it worked? Create a quick test file:

<?php
require 'vendor/autoload.php';

use ToonFormat\Toon;

echo "TOON library loaded successfully!\n";
echo "Version: " . Toon::VERSION;

If you see the version number, you're all set!

Step 2: Your First TOON Conversion

Let's start simple. You've got a PHP array, you want it in TOON format. Here's how:

Turning Arrays into TOON

Got some customer data? Let's convert it:

<?php
require 'vendor/autoload.php';

use ToonFormat\Toon;

// Your regular PHP array - nothing special here
$customers = [
    ['id' => 1, 'name' => 'Sienna Martinez', 'email' => '[email protected]', 'age' => 28],
    ['id' => 2, 'name' => 'Nora Chen', 'email' => '[email protected]', 'age' => 35],
    ['id' => 3, 'name' => 'Elara White', 'email' => '[email protected]', 'age' => 42]
];

// One line. That's all it takes.
$toonString = Toon::encode($customers);
echo $toonString;

/* Output:
customers[3]{id,name,email,age}:
  1,Sienna Martinez,[email protected],28
  2,Nora Chen,[email protected],35
  3,Elara White,[email protected],42
*/

What just happened? The Toon::encode() method looked at your array, figured out the structure, and converted it automatically. No configuration needed.

Going Back to PHP Arrays

Got TOON data and need it as a normal PHP array? Just as easy:

<?php
$toonData = <<<TOON
customers[3]{id,name,email,age}:
  1,Sienna Martinez,[email protected],28
  2,Nora Chen,[email protected],35
  3,Elara White,[email protected],42
TOON;

// Decode it back to a PHP array
$data = Toon::decode($toonData);

// Now you can use it like any other array
foreach ($data['customers'] as $customer) {
    echo "ID: {$customer['id']}, Name: {$customer['name']}\n";
}

/* Output:
ID: 1, Name: Sienna Martinez
ID: 2, Name: Nora Chen
ID: 3, Name: Elara White
*/

The result? A regular PHP associative array. Works exactly like you'd expect - no weird formats or special handling needed.

Step 3: Working with JSON

Already got JSON data lying around? Perfect. TOON plays nice with JSON - you can convert back and forth whenever you want:

JSON → TOON (The Money Saver)

<?php
$jsonString = '{
    "users": [
        {"id": 1, "name": "Sienna", "active": true},
        {"id": 2, "name": "Nora", "active": false}
    ]
}';

// Convert JSON directly to TOON
$toon = Toon::fromJson($jsonString);
echo $toon;

/* Output:
users[2]{id,name,active}:
  1,Sienna,true
  2,Nora,false
*/

// Or do it step-by-step if you prefer
$data = json_decode($jsonString, true);
$toon = Toon::encode($data);

Pro tip: This is where you'll see those token savings. That JSON above would use way more tokens in GPT-4.

TOON → JSON (When You Need It)

<?php
$toonString = 'users[2]{id,name,active}:
  1,Sienna,true
  2,Nora,false';

// Convert TOON back to JSON
$json = Toon::toJson($toonString);
echo $json;

/* Output:
{
    "users": [
        {"id": 1, "name": "Sienna", "active": true},
        {"id": 2, "name": "Nora", "active": false}
    ]
}
*/

// Or manually if you want more control
$data = Toon::decode($toonString);
$json = json_encode($data, JSON_PRETTY_PRINT);

Why would you convert back? Maybe you need to send data to an API that only accepts JSON, or export to a tool that doesn't understand TOON yet.

Step 4: The Real Reason You're Here - Saving Money with OpenAI

This is where TOON actually pays for itself. Every time you send data to GPT-4, you're paying per token. TOON uses about 50% fewer tokens than JSON. Let's see it in action:

Basic Example: Analyzing Customers

<?php
require 'vendor/autoload.php';

use ToonFormat\Toon;

// Your customer data
$customers = [
    ['id' => 1, 'name' => 'Sienna', 'plan' => 'Premium', 'mrr' => 299],
    ['id' => 2, 'name' => 'Nora', 'plan' => 'Basic', 'mrr' => 99],
    ['id' => 3, 'name' => 'Elara', 'plan' => 'Enterprise', 'mrr' => 999]
];

// Convert to TOON (this is what saves you money)
$toonData = Toon::encode($customers);

// Now send it to OpenAI
$apiKey = getenv('OPENAI_API_KEY');
$url = 'https://api.openai.com/v1/chat/completions';

$payload = [
    'model' => 'gpt-4',
    'messages' => [
        [
            'role' => 'system',
            'content' => 'You are a data analyst. Analyze customer data in TOON format.'
        ],
        [
            'role' => 'user',
            'content' => "Analyze this customer data and provide insights:\n\n" . $toonData
        ]
    ]
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $apiKey
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
echo $result['choices'][0]['message']['content'];

The math: If you sent this data as JSON, you'd use roughly double the tokens. Do this 1,000 times a day? That's real money saved.

Using the OpenAI PHP SDK

If you're using the official OpenAI SDK (and you probably should), it's even cleaner:

<?php
require 'vendor/autoload.php';

use OpenAI;
use ToonFormat\Toon;

$client = OpenAI::client(getenv('OPENAI_API_KEY'));

$customers = [
    ['id' => 1, 'name' => 'Sienna', 'plan' => 'Premium'],
    ['id' => 2, 'name' => 'Nora', 'plan' => 'Basic']
];

// Convert to TOON
$toonData = Toon::encode($customers);

$response = $client->chat()->create([
    'model' => 'gpt-4',
    'messages' => [
        ['role' => 'system', 'content' => 'Analyze data in TOON format.'],
        ['role' => 'user', 'content' => "Customer data:\n\n" . $toonData]
    ]
]);

echo $response->choices[0]->message->content;
echo "\n\nTokens used: " . $response->usage->totalTokens;

Bonus: The SDK shows you exactly how many tokens you used. Compare it with JSON to see your savings!

Step 5: Laravel Integration

If you're using Laravel, here's how to integrate TOON into your application:

Create a TOON Service

<?php
// app/Services/ToonService.php

namespace App\Services;

use ToonFormat\Toon;
use Illuminate\Support\Collection;

class ToonService
{
    public function encodeCollection(Collection $collection): string
    {
        return Toon::encode($collection->toArray());
    }
    
    public function encodeModel($model): string
    {
        return Toon::encode($model->toArray());
    }
    
    public function decode(string $toonData): array
    {
        return Toon::decode($toonData);
    }
    
    public function analyzeWithOpenAI(string $toonData, string $prompt): string
    {
        // Your OpenAI integration logic here
        $client = \OpenAI::client(config('services.openai.key'));
        
        $response = $client->chat()->create([
            'model' => 'gpt-4',
            'messages' => [
                ['role' => 'system', 'content' => 'Analyze TOON format data.'],
                ['role' => 'user', 'content' => $prompt . "\n\n" . $toonData]
            ]
        ]);
        
        return $response->choices[0]->message->content;
    }
}

Use in Controller

<?php
// app/Http/Controllers/CustomerAnalysisController.php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Services\ToonService;
use Illuminate\Http\Request;

class CustomerAnalysisController extends Controller
{
    public function __construct(
        private ToonService $toonService
    ) {}
    
    public function analyze(Request $request)
    {
        // Get customers from database
        $customers = Customer::where('active', true)
            ->select('id', 'name', 'email', 'plan', 'mrr')
            ->get();
        
        // Convert to TOON
        $toonData = $this->toonService->encodeCollection($customers);
        
        // Send to OpenAI for analysis
        $analysis = $this->toonService->analyzeWithOpenAI(
            $toonData,
            'Provide insights on these customers. Which customers are at risk of churning?'
        );
        
        return response()->json([
            'toon_data' => $toonData,
            'analysis' => $analysis
        ]);
    }
    
    public function export()
    {
        $customers = Customer::all();
        $toonData = $this->toonService->encodeCollection($customers);
        
        return response($toonData)
            ->header('Content-Type', 'text/plain')
            ->header('Content-Disposition', 'attachment; filename="customers.toon"');
    }
}

Custom Eloquent Cast (Advanced)

Create a custom cast to store TOON data in your database:

<?php
// app/Casts/Toon.php

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use ToonFormat\Toon as ToonFormat;

class Toon implements CastsAttributes
{
    public function get($model, string $key, $value, array $attributes)
    {
        return ToonFormat::decode($value);
    }

    public function set($model, string $key, $value, array $attributes)
    {
        return ToonFormat::encode($value);
    }
}

// Usage in Model:
// protected $casts = ['metadata' => Toon::class];

Step 6: Error Handling

Always handle potential errors when working with TOON:

<?php
use ToonFormat\Toon;
use ToonFormat\Exceptions\ToonParseException;
use ToonFormat\Exceptions\ToonValidationException;

try {
    // Parse TOON data
    $data = Toon::decode($toonString);
    
    // Validate structure
    if (!isset($data['customers'])) {
        throw new \Exception('Missing customers array');
    }
    
    // Process data
    foreach ($data['customers'] as $customer) {
        // Your logic here
    }
    
} catch (ToonParseException $e) {
    // Handle parsing errors
    error_log("TOON parsing error: " . $e->getMessage());
    return response()->json(['error' => 'Invalid TOON format'], 400);
    
} catch (ToonValidationException $e) {
    // Handle validation errors
    error_log("TOON validation error: " . $e->getMessage());
    return response()->json(['error' => 'Invalid TOON structure'], 422);
    
} catch (\Exception $e) {
    // Handle general errors
    error_log("Error: " . $e->getMessage());
    return response()->json(['error' => 'Processing failed'], 500);
}

// Validate before encoding
$data = ['users' => []];

if (empty($data['users'])) {
    throw new \Exception('Cannot encode empty data');
}

$toon = Toon::encode($data);

Best Practice: Always wrap TOON operations in try-catch blocks, especially when parsing user input or external data.

Step 7: Complete Real-World Example

Let's put it all together with a real-world customer analysis application:

Customer Insights API

<?php
// api/analyze-customers.php

require 'vendor/autoload.php';

use ToonFormat\Toon;

header('Content-Type: application/json');

try {
    // Get customer data from database
    $pdo = new PDO('mysql:host=localhost;dbname=myapp', 'user', 'password');
    
    $stmt = $pdo->prepare("
        SELECT id, name, email, plan, mrr, signup_date, last_active
        FROM customers
        WHERE active = 1
        ORDER BY mrr DESC
        LIMIT 100
    ");
    
    $stmt->execute();
    $customers = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Convert to TOON (saves ~50% tokens)
    $toonData = Toon::encode(['customers' => $customers]);
    
    // Send to OpenAI for analysis
    $apiKey = getenv('OPENAI_API_KEY');
    $url = 'https://api.openai.com/v1/chat/completions';
    
    $prompt = "Analyze these customers and provide:
1. Top 5 highest value customers
2. Customers at risk of churning (inactive > 30 days)
3. Upgrade opportunities (Basic users with high engagement)
4. Overall revenue trends";
    
    $payload = [
        'model' => 'gpt-4',
        'messages' => [
            [
                'role' => 'system',
                'content' => 'You are a customer success analyst. Analyze data in TOON format and provide actionable insights.'
            ],
            [
                'role' => 'user',
                'content' => $prompt . "\n\n" . $toonData
            ]
        ],
        'temperature' => 0.7
    ];
    
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $apiKey
        ],
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($payload),
        CURLOPT_RETURNTRANSFER => true
    ]);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($httpCode !== 200) {
        throw new Exception('OpenAI API request failed');
    }
    
    $result = json_decode($response, true);
    $analysis = $result['choices'][0]['message']['content'];
    $tokensUsed = $result['usage']['total_tokens'];
    
    // Calculate token savings
    $jsonData = json_encode(['customers' => $customers]);
    $jsonTokens = strlen($jsonData) / 4; // Rough estimate
    $toonTokens = strlen($toonData) / 4;
    $tokensSaved = $jsonTokens - $toonTokens;
    $percentSaved = ($tokensSaved / $jsonTokens) * 100;
    
    // Return response
    echo json_encode([
        'success' => true,
        'customer_count' => count($customers),
        'analysis' => $analysis,
        'stats' => [
            'tokens_used' => $tokensUsed,
            'tokens_saved' => round($tokensSaved),
            'percent_saved' => round($percentSaved, 1) . '%',
            'cost_estimate' => '$' . number_format($tokensUsed * 0.00001, 4)
        ]
    ], JSON_PRETTY_PRINT);
    
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'error' => $e->getMessage()
    ]);
}

What This Example Does:

  • Fetches customer data from MySQL database
  • Converts to TOON format (saves ~50% tokens)
  • Sends to GPT-4 for intelligent analysis
  • Returns insights with token usage statistics
  • Calculates actual cost savings vs. using JSON

Best Practices

Do This

  • • Use TOON for LLM API calls to save tokens
  • • Validate TOON data before parsing
  • • Cache TOON conversions when possible
  • • Use try-catch blocks for error handling
  • • Keep array structures consistent
  • • Document TOON field names clearly

Avoid This

  • • Don't use TOON for human-readable exports
  • • Don't skip validation on user input
  • • Don't mix inconsistent array structures
  • • Don't ignore parsing exceptions
  • • Don't use TOON for non-AI applications
  • • Don't forget to escape special characters

Performance Tips

1. Cache TOON Conversions

If you're converting the same data repeatedly, cache the TOON output:

$cacheKey = 'customers_toon_' . md5(serialize($customers));
$toonData = Cache::remember($cacheKey, 3600, function() use ($customers) {
    return Toon::encode($customers);
});

2. Use Streaming for Large Datasets

For very large datasets, process in chunks:

Customer::chunk(1000, function($customers) {
    $toonData = Toon::encode($customers->toArray());
    // Process each chunk
});

3. Select Only Needed Fields

Reduce data size by selecting only necessary columns:

$customers = Customer::select('id', 'name', 'plan', 'mrr')->get();
// Smaller TOON output = fewer tokens

Common Issues & Solutions

❌ Parse Error: "Invalid TOON format"

Cause: Malformed TOON string or missing syntax elements

Solution: Validate your TOON string using the TOON Validator

❌ Encoding Error: "Inconsistent array structure"

Cause: Arrays with different keys per element

Solution: Ensure all array elements have the same keys, or normalize your data before encoding

❌ Special Characters Break Parsing

Cause: Commas or newlines in string values

Solution: The library auto-escapes these, but validate output with Toon::validate($toonString)

Additional Resources

Related Guides

Other Languages

Ready to Reduce Your API Costs?

Start using TOON format in your PHP applications today and save ~50% on LLM token costs. Try converting your existing JSON data to see the difference.