Skip to content

Framework Integration

Rumen Damyanov edited this page Jul 31, 2025 · 1 revision

Framework Integration

Integration guides for Laravel, Symfony, and plain PHP applications.

Table of Contents

Laravel Integration

Auto-Discovery Setup

Laravel 5.5+ automatically discovers the service provider. No manual registration needed!

Manual Registration (Laravel < 5.5)

Add to config/app.php:

'providers' => [
    // Other providers...
    Rumenx\PhpChatbot\Adapters\Laravel\PhpChatbotServiceProvider::class,
],

Publishing Configuration

# Publish configuration file
php artisan vendor:publish --provider="Rumenx\PhpChatbot\Adapters\Laravel\PhpChatbotServiceProvider"

# Publish specific components
php artisan vendor:publish --provider="Rumenx\PhpChatbot\Adapters\Laravel\PhpChatbotServiceProvider" --tag=config
php artisan vendor:publish --provider="Rumenx\PhpChatbot\Adapters\Laravel\PhpChatbotServiceProvider" --tag=views
php artisan vendor:publish --provider="Rumenx\PhpChatbot\Adapters\Laravel\PhpChatbotServiceProvider" --tag=assets

Configuration File

After publishing, edit config/phpchatbot.php:

<?php
return [
    'model' => env('PHPCHATBOT_MODEL', 'openai'),
    'api_key' => env('OPENAI_API_KEY'),
    'model_name' => env('PHPCHATBOT_MODEL_NAME', 'gpt-3.5-turbo'),
    
    'prompt' => 'You are a helpful assistant for our website.',
    'temperature' => 0.7,
    'max_tokens' => 1000,
    
    // Laravel-specific features
    'use_laravel_cache' => true,
    'use_laravel_queue' => false,
    'use_laravel_logging' => true,
    
    'middleware' => ['web', 'throttle:60,1'],
    
    'route' => [
        'prefix' => 'api/chatbot',
        'middleware' => ['api'],
        'name' => 'chatbot.',
    ],
];

Basic Route Setup

Add to routes/web.php or routes/api.php:

use Illuminate\Http\Request;
use Rumenx\PhpChatbot\PhpChatbot;

Route::post('/chatbot/message', function (Request $request) {
    $chatbot = app('phpchatbot');
    
    $response = $chatbot->ask($request->input('message'));
    
    return response()->json(['reply' => $response]);
})->middleware(['throttle:10,1']);

Controller Implementation

Create app/Http/Controllers/ChatbotController.php:

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Rumenx\PhpChatbot\PhpChatbot;
use Rumenx\PhpChatbot\Models\ModelFactory;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;

class ChatbotController extends Controller
{
    private PhpChatbot $chatbot;
    
    public function __construct()
    {
        $config = config('phpchatbot');
        $model = ModelFactory::make($config);
        $this->chatbot = new PhpChatbot($model, $config);
    }
    
    public function message(Request $request): JsonResponse
    {
        $request->validate([
            'message' => 'required|string|max:2000',
            'conversation_id' => 'nullable|string|max:100',
        ]);
        
        $message = $request->input('message');
        $conversationId = $request->input('conversation_id');
        
        try {
            // Add conversation context
            $context = [
                'conversation_id' => $conversationId,
                'user_id' => auth()->id(),
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'logger' => Log::channel('chatbot'),
            ];
            
            $response = $this->chatbot->ask($message, $context);
            
            // Log conversation
            Log::info('Chatbot conversation', [
                'user_id' => auth()->id(),
                'message' => $message,
                'response' => $response,
                'conversation_id' => $conversationId,
            ]);
            
            return response()->json([
                'reply' => $response,
                'conversation_id' => $conversationId,
                'timestamp' => now()->toISOString(),
            ]);
            
        } catch (\Exception $e) {
            Log::error('Chatbot error', [
                'message' => $e->getMessage(),
                'user_id' => auth()->id(),
                'input' => $message,
            ]);
            
            return response()->json([
                'error' => 'Sorry, I encountered an error. Please try again.',
            ], 500);
        }
    }
    
    public function history(Request $request): JsonResponse
    {
        $conversationId = $request->input('conversation_id');
        
        // Retrieve conversation history from cache/database
        $history = Cache::get("chat_history_{$conversationId}", []);
        
        return response()->json(['history' => $history]);
    }
}

Route Registration

Add to routes/api.php:

use App\Http\Controllers\ChatbotController;

Route::prefix('chatbot')->middleware(['auth:sanctum'])->group(function () {
    Route::post('/message', [ChatbotController::class, 'message']);
    Route::get('/history', [ChatbotController::class, 'history']);
});

Middleware Integration

Create custom middleware app/Http/Middleware/ChatbotMiddleware.php:

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

class ChatbotMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        // Rate limiting
        $key = 'chatbot:' . $request->ip();
        
        if (RateLimiter::tooManyAttempts($key, 10)) {
            return response()->json([
                'error' => 'Too many requests. Please wait before trying again.'
            ], 429);
        }
        
        RateLimiter::hit($key, 60); // 60 seconds window
        
        // Input validation
        $message = $request->input('message');
        if (strlen($message) > 2000) {
            return response()->json([
                'error' => 'Message too long. Please keep it under 2000 characters.'
            ], 422);
        }
        
        return $next($request);
    }
}

Service Provider Customization

Create app/Providers/ChatbotServiceProvider.php:

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Rumenx\PhpChatbot\PhpChatbot;
use Rumenx\PhpChatbot\Models\ModelFactory;

class ChatbotServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton('phpchatbot', function ($app) {
            $config = config('phpchatbot');
            
            // Add Laravel-specific context
            $config['framework'] = 'laravel';
            $config['version'] = app()->version();
            
            $model = ModelFactory::make($config);
            return new PhpChatbot($model, $config);
        });
    }
    
    public function boot()
    {
        // Publish configuration
        $this->publishes([
            __DIR__.'/../../config/phpchatbot.php' => config_path('phpchatbot.php'),
        ], 'config');
        
        // Publish views
        $this->publishes([
            __DIR__.'/../../resources/views' => resource_path('views/vendor/phpchatbot'),
        ], 'views');
    }
}

Blade Integration

Create resources/views/chatbot/popup.blade.php:

<div id="chatbot-container" class="chatbot-container">
    <div id="chatbot-popup" class="chatbot-popup" style="display: none;">
        <div class="chatbot-header">
            <h4>{{ config('phpchatbot.ui.title', 'Chat Support') }}</h4>
            <button id="chatbot-close">&times;</button>
        </div>
        <div id="chatbot-messages" class="chatbot-messages">
            <div class="chatbot-message bot-message">
                {{ config('phpchatbot.ui.greeting', 'Hello! How can I help you?') }}
            </div>
        </div>
        <div class="chatbot-input">
            <input type="text" id="chatbot-input" placeholder="{{ config('phpchatbot.ui.placeholder', 'Type your message...') }}">
            <button id="chatbot-send">{{ config('phpchatbot.ui.send_button', 'Send') }}</button>
        </div>
    </div>
    <button id="chatbot-toggle" class="chatbot-toggle">💬</button>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
    const chatbot = {
        conversationId: null,
        
        init() {
            this.bindEvents();
            this.conversationId = this.generateConversationId();
        },
        
        bindEvents() {
            document.getElementById('chatbot-toggle').addEventListener('click', this.toggle);
            document.getElementById('chatbot-close').addEventListener('click', this.close);
            document.getElementById('chatbot-send').addEventListener('click', this.sendMessage);
            document.getElementById('chatbot-input').addEventListener('keypress', (e) => {
                if (e.key === 'Enter') this.sendMessage();
            });
        },
        
        toggle() {
            const popup = document.getElementById('chatbot-popup');
            popup.style.display = popup.style.display === 'none' ? 'block' : 'none';
        },
        
        close() {
            document.getElementById('chatbot-popup').style.display = 'none';
        },
        
        async sendMessage() {
            const input = document.getElementById('chatbot-input');
            const message = input.value.trim();
            
            if (!message) return;
            
            this.addMessage(message, 'user');
            input.value = '';
            
            try {
                const response = await fetch('/api/chatbot/message', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
                        'Authorization': 'Bearer ' + localStorage.getItem('api_token'),
                    },
                    body: JSON.stringify({
                        message: message,
                        conversation_id: this.conversationId,
                    }),
                });
                
                const data = await response.json();
                
                if (data.reply) {
                    this.addMessage(data.reply, 'bot');
                } else {
                    this.addMessage('Sorry, I encountered an error.', 'bot');
                }
            } catch (error) {
                this.addMessage('Network error. Please try again.', 'bot');
            }
        },
        
        addMessage(text, sender) {
            const messages = document.getElementById('chatbot-messages');
            const messageDiv = document.createElement('div');
            messageDiv.className = `chatbot-message ${sender}-message`;
            messageDiv.textContent = text;
            messages.appendChild(messageDiv);
            messages.scrollTop = messages.scrollHeight;
        },
        
        generateConversationId() {
            return 'conv_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
        }
    };
    
    chatbot.init();
});
</script>

@push('styles')
<link href="{{ asset('css/chatbot.css') }}" rel="stylesheet">
@endpush

Symfony Integration

Bundle Registration

Add to config/bundles.php:

<?php
return [
    // Other bundles...
    Rumenx\PhpChatbot\Adapters\Symfony\PhpChatbotBundle::class => ['all' => true],
];

Configuration

Create config/packages/phpchatbot.yaml:

phpchatbot:
    model: '%env(PHPCHATBOT_MODEL)%'
    api_key: '%env(OPENAI_API_KEY)%'
    model_name: '%env(PHPCHATBOT_MODEL_NAME)%'
    
    prompt: 'You are a helpful assistant for our Symfony application.'
    temperature: 0.7
    max_tokens: 1000
    
    # Symfony-specific features
    use_symfony_cache: true
    use_symfony_logger: true
    cache_pool: 'app.cache.chatbot'
    
    security:
        csrf_protection: true
        session_validation: true
        
    routing:
        prefix: '/api/chatbot'
        requirements:
            _locale: 'en|es|fr'

Service Configuration

Add to config/services.yaml:

services:
    # Chatbot service
    Rumenx\PhpChatbot\PhpChatbot:
        arguments:
            $config: '%phpchatbot%'
        tags: ['controller.service_arguments']
    
    # Custom chatbot service
    App\Service\ChatbotService:
        arguments:
            $chatbot: '@Rumenx\PhpChatbot\PhpChatbot'
            $logger: '@logger'
            $cache: '@cache.app'
        tags: ['monolog.logger', { channel: 'chatbot' }]

Controller Implementation

Create src/Controller/ChatbotController.php:

<?php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Rumenx\PhpChatbot\PhpChatbot;
use Psr\Log\LoggerInterface;

#[Route('/api/chatbot', name: 'chatbot_')]
class ChatbotController extends AbstractController
{
    public function __construct(
        private PhpChatbot $chatbot,
        private LoggerInterface $logger,
        private RateLimiterFactory $chatbotLimiter
    ) {}
    
    #[Route('/message', name: 'message', methods: ['POST'])]
    public function message(Request $request): JsonResponse
    {
        // Rate limiting
        $limiter = $this->chatbotLimiter->create($request->getClientIp());
        if (!$limiter->consume()->isAccepted()) {
            return $this->json(['error' => 'Rate limit exceeded'], 429);
        }
        
        $data = json_decode($request->getContent(), true);
        $message = $data['message'] ?? '';
        $conversationId = $data['conversation_id'] ?? null;
        
        if (empty($message) || strlen($message) > 2000) {
            return $this->json(['error' => 'Invalid message'], 400);
        }
        
        try {
            $context = [
                'conversation_id' => $conversationId,
                'user_id' => $this->getUser()?->getId(),
                'session_id' => $request->getSession()->getId(),
                'locale' => $request->getLocale(),
                'logger' => $this->logger,
            ];
            
            $response = $this->chatbot->ask($message, $context);
            
            $this->logger->info('Chatbot conversation', [
                'user_id' => $this->getUser()?->getId(),
                'message' => $message,
                'response' => $response,
                'conversation_id' => $conversationId,
            ]);
            
            return $this->json([
                'reply' => $response,
                'conversation_id' => $conversationId,
                'timestamp' => (new \DateTime())->format(\DateTime::ATOM),
            ]);
            
        } catch (\Exception $e) {
            $this->logger->error('Chatbot error', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            
            return $this->json(['error' => 'Internal error'], 500);
        }
    }
    
    #[Route('/history/{conversationId}', name: 'history', methods: ['GET'])]
    public function history(string $conversationId): JsonResponse
    {
        // Implement conversation history retrieval
        return $this->json(['history' => []]);
    }
}

Event Subscriber

Create src/EventSubscriber/ChatbotSubscriber.php:

<?php
namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class ChatbotSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::REQUEST => 'onKernelRequest',
        ];
    }
    
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();
        
        // Add chatbot-specific headers or processing
        if (str_starts_with($request->getPathInfo(), '/api/chatbot')) {
            $request->headers->set('X-Chatbot-Request', 'true');
        }
    }
}

Twig Integration

Create templates/chatbot/widget.html.twig:

<div id="chatbot-widget" data-config="{{ chatbot_config|json_encode }}">
    <div id="chatbot-popup" class="chatbot-popup" style="display: none;">
        <div class="chatbot-header">
            <h4>{{ 'chatbot.title'|trans }}</h4>
            <button id="chatbot-close" class="chatbot-close">&times;</button>
        </div>
        <div id="chatbot-messages" class="chatbot-messages">
            <div class="chatbot-message bot-message">
                {{ 'chatbot.greeting'|trans }}
            </div>
        </div>
        <div class="chatbot-input">
            <input type="text" 
                   id="chatbot-input" 
                   placeholder="{{ 'chatbot.placeholder'|trans }}">
            <button id="chatbot-send">{{ 'chatbot.send'|trans }}</button>
        </div>
    </div>
    <button id="chatbot-toggle" class="chatbot-toggle">
        💬
    </button>
</div>

{% block javascripts %}
    {{ parent() }}
    <script src="{{ asset('js/chatbot-symfony.js') }}"></script>
{% endblock %}

Plain PHP Integration

Basic Setup

Create src/Chatbot/ChatbotManager.php:

<?php
namespace App\Chatbot;

use Rumenx\PhpChatbot\PhpChatbot;
use Rumenx\PhpChatbot\Models\ModelFactory;

class ChatbotManager
{
    private PhpChatbot $chatbot;
    private array $config;
    
    public function __construct(string $configPath = null)
    {
        $configPath = $configPath ?: __DIR__ . '/../../config/phpchatbot.php';
        $this->config = require $configPath;
        
        $model = ModelFactory::make($this->config);
        $this->chatbot = new PhpChatbot($model, $this->config);
    }
    
    public function handleRequest(): void
    {
        header('Content-Type: application/json');
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: POST, OPTIONS');
        header('Access-Control-Allow-Headers: Content-Type');
        
        if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
            http_response_code(200);
            exit;
        }
        
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            http_response_code(405);
            echo json_encode(['error' => 'Method not allowed']);
            exit;
        }
        
        $this->processMessage();
    }
    
    private function processMessage(): void
    {
        try {
            // Rate limiting
            $this->checkRateLimit();
            
            // Get input
            $input = json_decode(file_get_contents('php://input'), true);
            $message = $input['message'] ?? '';
            
            if (empty($message) || strlen($message) > 2000) {
                throw new \Exception('Invalid message');
            }
            
            // Process message
            $context = [
                'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
                'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
                'timestamp' => date('Y-m-d H:i:s'),
            ];
            
            $response = $this->chatbot->ask($message, $context);
            
            // Log conversation
            $this->logConversation($message, $response, $context);
            
            echo json_encode([
                'reply' => $response,
                'timestamp' => date('c'),
            ]);
            
        } catch (\Exception $e) {
            http_response_code(500);
            echo json_encode(['error' => $e->getMessage()]);
            
            // Log error
            error_log("Chatbot error: " . $e->getMessage());
        }
    }
    
    private function checkRateLimit(): void
    {
        $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        $key = 'chatbot_rate_' . md5($ip);
        $limit = $this->config['rate_limit'] ?? 10;
        $window = $this->config['rate_window'] ?? 60;
        
        // Simple file-based rate limiting
        $cacheFile = sys_get_temp_dir() . '/' . $key;
        $now = time();
        
        if (file_exists($cacheFile)) {
            $data = json_decode(file_get_contents($cacheFile), true);
            $data = array_filter($data, fn($time) => $now - $time < $window);
            
            if (count($data) >= $limit) {
                throw new \Exception('Rate limit exceeded');
            }
            
            $data[] = $now;
        } else {
            $data = [$now];
        }
        
        file_put_contents($cacheFile, json_encode($data));
    }
    
    private function logConversation(string $message, string $response, array $context): void
    {
        if (!($this->config['enable_logging'] ?? true)) {
            return;
        }
        
        $logEntry = [
            'timestamp' => date('Y-m-d H:i:s'),
            'ip' => $context['ip_address'],
            'message' => $message,
            'response' => $response,
        ];
        
        $logFile = $this->config['log_file'] ?? 'chatbot.log';
        file_put_contents($logFile, json_encode($logEntry) . "\n", FILE_APPEND);
    }
}

API Endpoint

Create public/api/chatbot.php:

<?php
require_once __DIR__ . '/../../vendor/autoload.php';

use App\Chatbot\ChatbotManager;

try {
    $chatbot = new ChatbotManager();
    $chatbot->handleRequest();
} catch (\Exception $e) {
    http_response_code(500);
    echo json_encode(['error' => 'Server error']);
    error_log("Chatbot initialization error: " . $e->getMessage());
}

Frontend Integration

Create public/js/chatbot.js:

class PlainPHPChatbot {
    constructor(options = {}) {
        this.apiUrl = options.apiUrl || '/api/chatbot.php';
        this.container = options.container || 'chatbot-container';
        this.init();
    }
    
    init() {
        this.createHTML();
        this.bindEvents();
    }
    
    createHTML() {
        const container = document.getElementById(this.container);
        container.innerHTML = `
            <div id="chatbot-popup" class="chatbot-popup" style="display: none;">
                <div class="chatbot-header">
                    <h4>Chat Support</h4>
                    <button id="chatbot-close">&times;</button>
                </div>
                <div id="chatbot-messages" class="chatbot-messages">
                    <div class="chatbot-message bot-message">
                        Hello! How can I help you today?
                    </div>
                </div>
                <div class="chatbot-input">
                    <input type="text" id="chatbot-input" placeholder="Type your message...">
                    <button id="chatbot-send">Send</button>
                </div>
            </div>
            <button id="chatbot-toggle" class="chatbot-toggle">💬</button>
        `;
    }
    
    bindEvents() {
        document.getElementById('chatbot-toggle').onclick = () => this.toggle();
        document.getElementById('chatbot-close').onclick = () => this.close();
        document.getElementById('chatbot-send').onclick = () => this.sendMessage();
        document.getElementById('chatbot-input').onkeypress = (e) => {
            if (e.key === 'Enter') this.sendMessage();
        };
    }
    
    toggle() {
        const popup = document.getElementById('chatbot-popup');
        popup.style.display = popup.style.display === 'none' ? 'block' : 'none';
    }
    
    close() {
        document.getElementById('chatbot-popup').style.display = 'none';
    }
    
    async sendMessage() {
        const input = document.getElementById('chatbot-input');
        const message = input.value.trim();
        
        if (!message) return;
        
        this.addMessage(message, 'user');
        input.value = '';
        
        try {
            const response = await fetch(this.apiUrl, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ message })
            });
            
            const data = await response.json();
            
            if (data.reply) {
                this.addMessage(data.reply, 'bot');
            } else if (data.error) {
                this.addMessage('Error: ' + data.error, 'bot error');
            }
        } catch (error) {
            this.addMessage('Network error. Please try again.', 'bot error');
        }
    }
    
    addMessage(text, className) {
        const messages = document.getElementById('chatbot-messages');
        const div = document.createElement('div');
        div.className = `chatbot-message ${className}`;
        div.textContent = text;
        messages.appendChild(div);
        messages.scrollTop = messages.scrollHeight;
    }
}

// Initialize when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
    new PlainPHPChatbot();
});

Other Frameworks

CodeIgniter 4

<?php
namespace App\Controllers;

use CodeIgniter\RESTful\ResourceController;
use Rumenx\PhpChatbot\PhpChatbot;
use Rumenx\PhpChatbot\Models\ModelFactory;

class Chatbot extends ResourceController
{
    protected $format = 'json';
    
    public function message()
    {
        $config = config('Chatbot');
        $model = ModelFactory::make($config);
        $chatbot = new PhpChatbot($model, $config);
        
        $message = $this->request->getJSON()->message ?? '';
        
        try {
            $response = $chatbot->ask($message);
            return $this->respond(['reply' => $response]);
        } catch (\Exception $e) {
            return $this->respond(['error' => $e->getMessage()], 500);
        }
    }
}

CakePHP

<?php
namespace App\Controller;

use Cake\Controller\Controller;
use Rumenx\PhpChatbot\PhpChatbot;
use Rumenx\PhpChatbot\Models\ModelFactory;

class ChatbotController extends Controller
{
    public function initialize(): void
    {
        parent::initialize();
        $this->loadComponent('RequestHandler');
    }
    
    public function message()
    {
        $this->request->allowMethod(['post']);
        
        $config = Configure::read('Chatbot');
        $model = ModelFactory::make($config);
        $chatbot = new PhpChatbot($model, $config);
        
        $message = $this->request->getData('message');
        
        try {
            $response = $chatbot->ask($message);
            $this->set(['reply' => $response]);
            $this->viewBuilder()->setOption('serialize', ['reply']);
        } catch (\Exception $e) {
            $this->response = $this->response->withStatus(500);
            $this->set(['error' => $e->getMessage()]);
            $this->viewBuilder()->setOption('serialize', ['error']);
        }
    }
}

Custom Adapters

Creating a Custom Adapter

<?php
namespace App\Adapters;

use Rumenx\PhpChatbot\Contracts\AdapterInterface;
use Rumenx\PhpChatbot\PhpChatbot;

class CustomFrameworkAdapter implements AdapterInterface
{
    private $framework;
    
    public function __construct($framework)
    {
        $this->framework = $framework;
    }
    
    public function register(PhpChatbot $chatbot): void
    {
        // Register chatbot with your framework
        $this->framework->singleton('chatbot', function() use ($chatbot) {
            return $chatbot;
        });
    }
    
    public function getConfig(): array
    {
        // Load configuration from your framework
        return $this->framework->config('chatbot');
    }
    
    public function log(string $message, array $context = []): void
    {
        // Use your framework's logging
        $this->framework->log()->info($message, $context);
    }
    
    public function cache(string $key, $value, int $ttl = 3600): void
    {
        // Use your framework's caching
        $this->framework->cache()->put($key, $value, $ttl);
    }
}

Next: Frontend Integration

Clone this wiki locally