DEV Community

Javier Eguiluz
Javier Eguiluz

Posted on

8 1

How to Make ChatGPT Codex Work with PHP and Symfony

Codex is a cloud-based coding agent created by OpenAI. It can run multiple tasks in parallel to fix bugs, implement features, suggest improvements, and more. It can even create pull requests on platforms like GitHub.

Although Codex already works well with PHP, providing solid code suggestions and improvements, its most powerful feature is that it can run your code (e.g., executing your test suite) to verify that its proposed changes actually work. This is a game-changer for languages like Python or JavaScript, where code execution is supported out of the box.

PHP, however, is not natively supported for code execution. This article explains how to make Codex work effectively with PHP and Symfony applications, including how to configure it to run your test suite and validate changes automatically.

As of this writing, Codex is available to Plus ($20/month) and Pro ($200/month) ChatGPT users, but not to free-tier users.

Setting Up the Environment

Visit chatgpt.com/codex and follow the on-screen steps to connect Codex to your GitHub repositories. You'll see which repositories you can import directly and which ones require admin approval if you only have limited access.

Before Codex can work with a repository, you need to create an environment for it. An environment defines how Codex interacts with your code.

Go to chatgpt.com/codex/settings/environments and click the Create environment button. Each environment is tied to a single GitHub repository, so you'll need to create one environment per repo.

In the Basic section, choose the GitHub organization and repository of your PHP/Symfony project:

Basic configuration of Codex environments

In the Code execution section, configure the following options:

Code Execution configuration of Codex environments

  • Container image: Codex tasks run your code inside a Docker container. Currently, only the universal image provided by Codex is available. Support for custom images is coming soon. Check the list of default installed packages in the universal image.
  • Environment variables and Secrets: self-explanatory; covered later in this article.
  • Setup script: this is the critical part for PHP/Symfony projects. It's used to install PHP, Composer, and other tools not included in the default image. A full example is provided below.
  • Agent internet access: disabled by default. Enable it only if you absolutely need it (e.g., to download dependencies). Even OpenAI recommends keeping it off. Instead, use the setup script to download everything you need, as explained below.

Setup Script

The setup script runs at the beginning of every task, after the repository is cloned. It's your chance to prepare the environment for PHP/Symfony development and testing. Internet access is always enabled during this step, so you can install dependencies here even if it's disabled later.

Here's a full example I use for Symfony apps. Once you've saved your environment, click Connect interactive terminal to test and debug the script in the actual container Codex will use for tasks.

#!/usr/bin/env bash
# this makes the script strict:
#   -e: exit on any error
#   -u: error on undefined variables
#   -o pipefail: exit if any command in a pipeline fails
set -euo pipefail

# Adds a package repository that provides the latest PHP versions
# (see https://deb.sury.org/ for details)
add-apt-repository -y ppa:ondrej/php
# Updates package lists to get the latest information about available packages
apt-get update

# Install PHP 8.4 and extensions commonly needed for Symfony applications
apt-get install -y \
    php8.4 \
    php8.4-cli \
    php8.4-mbstring \
    php8.4-xml \
    php8.4-intl \
    php8.4-gd \
    php8.4-zip \
    php8.4-curl \
    php8.4-pgsql # this is for PostgreSQL; change this if you use MySQL

# This makes PHP 8.4 available through the global 'php' binary,
# which is expected by many commands
update-alternatives --install /usr/bin/php php /usr/bin/php8.4 84
update-alternatives --set php /usr/bin/php8.4

# Install Composer as a global 'composer' binary following the safest practices
EXPECTED_CHECKSUM="$(curl -fsSL https://composer.github.io/installer.sig)"
curl -fsSL https://getcomposer.org/installer -o composer-setup.php
ACTUAL_CHECKSUM="$(sha384sum composer-setup.php | cut -d ' ' -f 1)"
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then
    echo 'ERROR: Invalid composer installer checksum.' >&2
    rm composer-setup.php
    exit 1
fi
php composer-setup.php --install-dir=/usr/local/bin --filename=composer --quiet
rm composer-setup.php

# Install the PHP dependencies of your project;
# private packages require some more work explained later in this article
composer install

# Show installed versions to check if everything worked
php -v
composer --version
Enter fullscreen mode Exit fullscreen mode

Private Composer Packages

If your project depends on private Composer packages (e.g., from GitHub), you'll need to authenticate Composer.

(1) Create a personal access token: either a classic token or a fine-grained token. Name it something like "OpenAI Codex" and give it read access to the private repositories.

(2) Add the token to Codex: go to your Codex environment settings, scroll to Secrets, and click Add +. Name the secret COMPOSER_AUTH. The value must be a JSON-encoded element with the token that you created earlier. The format is the same as used in the file ~/.composer/auth.json but you must put everything in a single line. For example:

{"github-oauth":{"github.com": "ghp_fs2dWqUilbS0NBeJaWBw3QgIucTO5RyrXV1e"}}
Enter fullscreen mode Exit fullscreen mode

Optionally, you can add a check in your setup script to make sure this secret is set:

#!/usr/bin/env bash
set -euo pipefail

# the script will fail if this env var / secret is not set
: "${COMPOSER_AUTH:?}"

# ...
Enter fullscreen mode Exit fullscreen mode

Using Databases

If your test suite requires a database (e.g., MySQL or PostgreSQL), you'll need to install and configure it in the setup script. Here's how to do it:

First, define the following environment variables: POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB. These can use dummy values for local test databases. Make sure they match the values used in the DATABASE_DSN option of your Symfony application.

Then add these to the top of your script to verify they're defined:

#!/usr/bin/env bash
set -euo pipefail

# make sure the required env vars are defined
: "${COMPOSER_AUTH:?}"
: "${POSTGRES_USER:?}"
: "${POSTGRES_PASSWORD:?}"
: "${POSTGRES_DB:?}"

# ...
Enter fullscreen mode Exit fullscreen mode

Next, install PostgreSQL:

# Update package lists
# ...

# Install PostgreSQL
apt-get install -y --no-install-recommends postgresql-16

# Install PHP and common extensions
# ...
Enter fullscreen mode Exit fullscreen mode

Start PostgreSQL and create the user/database:

# Install Composer
# ...

# Install dependencies
# ...

# Start PostgreSQL
pg_dropcluster --stop 16 main || true
pg_createcluster --start -u postgres 16 main

# Create the PostgreSQL user and database
su postgres -c "createuser -s \"${POSTGRES_USER}\""
su postgres -c "psql -c \"ALTER USER \\\"${POSTGRES_USER}\\\" WITH PASSWORD '${POSTGRES_PASSWORD}';\""
su postgres -c "createdb -O \"${POSTGRES_USER}\" \"${POSTGRES_DB}\""

# (Optional) Verify that the user can log in
# psql -U $POSTGRES_USER -d $POSTGRES_DB

# Show installed versions
# ...
psql --version
Enter fullscreen mode Exit fullscreen mode

General Settings

Before running your first task, visit chatgpt.com/codex/settings/general to configure global settings used across all projects:

  • Custom instructions: used to customize the behavior of Codex; e.g., "Always use English for code, comments, commits, and branch names", "Use concise branch names prefixed with feat- or bug-", etc.
  • Branch format: defaults to codex/{feature} but you can change it to {feature} or anything else.

Providing Metadata to Agents

Although optional, adding metadata files can significantly improve how agents like Codex understand and navigate your codebase. These plain-text files describe how
to run tests, what conventions to follow, and more. With good metadata, you'll get more accurate results and fewer mistakes.

There's no universal standard yet, so you'll need one file per agent. In my projects, I use:

  • <project-root>/AGENTS.md for ChatGPT Codex
  • <project-root>/CLAUDE.md for Claude AI
  • <project-root>/.github/copilot-instructions.md for GitHub Copilot

All three files usually share the same content. You can create one file and use symlinks for the others. Claude also supports importing files using:

See @AGENTS.md
Enter fullscreen mode Exit fullscreen mode

You can see a real-world example of the AGENTS.md file I use in one of my projects. As you run tasks, update this file continuously with new instructions to prevent Codex from making the same mistakes again.

Security and Privacy Recommendations

In addition to disabling Agent internet access, you should review the privacy settings at chatgpt.com/codex/settings/data:

  • Model improvement: enabled by default; allows OpenAI to use your code to improve their models.
  • Include environments: lets OpenAI learn from your Codex environment settings.

Wrapping Up

Out of the box, ChatGPT Codex doesn't support executing PHP code, which limits its potential. But with the right setup, you can unlock full task automation in Symfony and PHP projects.

Once configured, Codex becomes more than a code reviewer: it becomes a real coding assistant that understands your stack and validates its own changes.

Try it out and leave your comments if you have any question so I can update this article.


✨ If you enjoyed this or any of my other articles and want to support my work, consider sponsoring me on GitHub 🙌


Top comments (6)

Collapse
 
joppedc profile image
JoppeDC

Great post Javier!

Collapse
 
xwero profile image
david duymelinck

For the metadata file wouldn't it be easier to direct the AI to the linter config, static analysis config, and composer file for more information?
Why would you do that work twice, just for AI to understand the codebase and the rules better?

Collapse
 
javiereguiluz profile image
Javier Eguiluz

When doing that or not mentioning anything at all about commands, things didn't work perfectly for me (it worked occasionally/randomly). That's why I prefer to be very explicit about this. But, Codex and others keep improving every day, so maybe this is already solved or will be soon.

Collapse
 
gavriel_adi profile image
גבריאל עדי

The question is how to work with OpenAI Codex with pure PHP and a MYSQL database?

Collapse
 
javiereguiluz profile image
Javier Eguiluz

Most of the article contents will help you when running pure PHP applications without Symfony.

About MySQL, I don't know the specifics for that database, but it's so popular that you can probably find some resources about how to set it up.

Collapse
 
jaycee_4790425dbab36922cb profile image
Jaycee

thanks for this! extremely helpful.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

👋 Kindness is contagious

Discover this thought-provoking article in the thriving DEV Community. Developers of every background are encouraged to jump in, share expertise, and uplift our collective knowledge.

A simple "thank you" can make someone's day—drop your kudos in the comments!

On DEV, spreading insights lights the path forward and bonds us. If you appreciated this write-up, a brief note of appreciation to the author speaks volumes.

Get Started