HuTor Tech logo HuTor Tech
← All posts

· hutor.tech

How to add OpenAI to an existing PHP application

How to add OpenAI to an existing PHP application

Adding a language model to an existing PHP application is an integration task, not an AI project. The model is a remote service that is slow, occasionally unavailable and billed per token — treat it exactly like a payment gateway and most of the design follows.

Start with one narrow job. "Summarise this ticket", "extract the delivery address from this message", "write the meta description for this product" are all shippable in a day and easy to evaluate. "Add AI to the site" is not a task, and projects that begin that way tend to end with an expensive chat widget nobody uses.

Keep the key on the server and out of the repository. It belongs in `.env`, read through `config/services.php` in Laravel, never in JavaScript and never in a template. A key that reaches the browser is a key that pays for someone else's traffic.

Call the API from a queued job, not from the controller. A request that waits for a model can take ten seconds or time out entirely; a user should never sit through that. Save the record first, dispatch the job, show the result when it arrives. In a Laravel application that is a few lines; in a legacy application, a cron-driven worker table does the same thing well enough.

Wrap the call in the same defences you give any third-party service:
— a timeout, so a slow answer cannot hold a worker forever;
— retries with a backoff for rate limits and 5xx responses;
— a cache keyed by the input, so the same product description is never paid for twice;
— a hard cap on tokens and on how many calls a single user can trigger;
— logging of the request id, the token usage and the cost.

Ask for structured output when the answer feeds your code. A model that returns free text forces you to parse prose; a model constrained to a JSON schema returns fields you can validate. Then validate them anyway — the output of a language model is user input as far as your application is concerned, and it must never be interpolated into SQL, shell commands or HTML without escaping.

Finally, decide what happens when the model is wrong, because it will be. Show the generated text as a draft a human approves, keep the original alongside the generated version, and make the feature degrade to the old behaviour when the API is down. An integration nobody can turn off is an integration that will eventually take the site with it.