When I first connected a simple HTML form with PHP and Postgres using PDO, everything looked fine on the front-end until I hit “Submit.” Instead of a smooth database insert, my browser console simply printed:
Okay, I failed [object Object]
At first, I thought my Ajax call was broken, but after digging deeper, I discovered that the real problem was in my PHP. In this post, I’ll walk you through the original issue, the root cause, and how I fixed it. I’ll also share the final working code along with a few practice improvements I added to make the project more robust.
The Setup
I had an HTML form with seven fields: date, email, first name, last name, password, comments, and a checkbox. On submit, I used jQuery Ajax to collect and send the data:
<form id="registerForm">
<input type="date" name="datefield" required>
<input type="email" name="email_field" required>
<input type="text" name="firstname" required>
<input type="text" name="lastname" required>
<input type="password" name="password" required minlength="8">
<input type="text" name="comments">
<input type="checkbox" name="checkbox" value="true">
<button id="submitBtn" type="button">Register</button>
</form>
<div id="msg" style="margin-top:1rem;"></div>
<ul id="recent"></ul>
And here’s the JavaScript I used to send the request:
function collectData() {
const $btn = $("#submitBtn");
const $msg = $("#msg");
const form_data = $('#registerForm').serialize();
console.log("CollectData start", form_data);
$btn.prop("disabled", true);
$msg.text("Submitting…");
return $.ajax({
type: "POST",
url: "register.php",
data: form_data,
dataType: "json"
})
.done(function (res) {
if (res.ok) {
$msg.text("Saved! New id: " + res.id);
$("#registerForm")[0].reset();
loadRecent();
} else {
$msg.text("Server rejected: " + (res.error || "Unknown error"));
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
console.error("AJAX fail:", { textStatus, errorThrown, response: jqXHR.responseText });
let msg = "Request failed: " + textStatus;
if (jqXHR.responseJSON && jqXHR.responseJSON.error) msg += " — " + jqXHR.responseJSON.error;
else if (jqXHR.responseText) msg += " — " + jqXHR.responseText;
$msg.text(msg);
})
.always(function () {
$btn.prop("disabled", false);
});
}
$("#submitBtn").on("click", collectData);
The Ajax side worked the form data showed up in the console. But the PHP side blew up.
The Error
In my logs (/var/log/apache2/error.log
) I found this:
PHP Parse error: syntax error, unexpected ''user'' (T_CONSTANT_ENCAPSED_STRING), expecting ']' in /var/www/html/register.php on line 9
And earlier, I also saw:
PHP Startup: Unable to load dynamic library 'pdo_pgsql'
So I had two problems:
- My
$params
array had a missing comma'port' => '5432' 'user' => '...'
is invalid PHP. - PDO wasn’t connected at all because I never actually created a
$pdo
instance. Even worse,pdo_pgsql
wasn’t installed properly on my server.
No wonder Ajax was only showing [object Object]
my PHP script died before it returned anything useful.
The Fix
First, I installed the missing extension:
sudo apt-get install php-pgsql
sudo service apache2 reload
Then I rewrote register.php
properly:
<?php
declare(strict_types=1);
header('Content-Type: application/json');
try {
$host = '127.0.0.1';
$port = '5432';
$db = 'dbase01';
$user = 'your_user';
$pwd = 'your_password';
$dsn = "pgsql:host=$host;port=$port;dbname=$db";
$pdo = new PDO($dsn, $user, $pwd, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
$required = ['datefield','email_field','firstname','lastname','password'];
foreach ($required as $key) {
if (!isset($_POST[$key]) || $_POST[$key] === '') {
http_response_code(400);
echo json_encode(['ok'=>false, 'error'=>"Missing field: $key"]);
exit;
}
}
$comments = $_POST['comments'] ?? null;
$checkbox = isset($_POST['checkbox']) && $_POST['checkbox'] === 'true';
$pdo->beginTransaction();
$sql = 'INSERT INTO qsq01 ("datefield","email_field","firstname","lastname","password","comments","checkbox")
VALUES (:datefield,:email_field,:firstname,:lastname,:password,:comments,:checkbox)
RETURNING id';
$stmt = $pdo->prepare($sql);
$stmt->execute([
':datefield' => $_POST['datefield'],
':email_field' => $_POST['email_field'],
':firstname' => $_POST['firstname'],
':lastname' => $_POST['lastname'],
':password' => password_hash($_POST['password'], PASSWORD_DEFAULT),
':comments' => $comments,
':checkbox' => $checkbox,
]);
$newId = $stmt->fetchColumn();
$pdo->commit();
echo json_encode(['ok'=>true, 'id'=>$newId]);
} catch (Throwable $e) {
if (isset($pdo) && $pdo->inTransaction()) {
$pdo->rollBack();
}
error_log($e);
http_response_code(500);
echo json_encode(['ok'=>false, 'error'=>'Server error (see logs)']);
}
Notice the changes:
- I built a real DSN string for Postgres (
pgsql:host=...;port=...;dbname=...
). - I wrapped everything in a
try/catch
and returned clear JSON responses. - I quoted Postgres identifiers correctly (
"colname"
instead of'colname'
). - I hashed the password with
password_hash()
for security.
Practice Functionality
To make the project more fun (and useful), I added a little endpoint to show the last 10 inserted rows:
// recent.php
<?php
header('Content-Type: application/json');
$pdo = new PDO("pgsql:host=127.0.0.1;port=5432;dbname=dbase01", "your_user", "your_password", [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$rows = $pdo->query('SELECT id, datefield, email_field, firstname, lastname FROM qsq01 ORDER BY id DESC LIMIT 10')->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($rows);
And in JavaScript, I created a loadRecent()
function that refreshes the list after each successful insert. This gave me immediate feedback and confidence that the form actually worked.
What I Learn
Here’s what bit me:
- A missing comma in PHP can take down your whole script.
- If you don’t actually create a PDO connection, nothing else matters.
[object Object]
in the browser console isn’t a helpful error — you need to logjqXHR.responseText
to see the real backend message.- Postgres requires double quotes for identifiers, not single quotes.
- PHP extensions like
pdo_pgsql
must be installed and enabled before anything will connect.
Final Thought
This little debugging journey taught me that when an Ajax call fails mysteriously, the real problem is often buried in the server logs. Once I cleaned up the PHP, enabled pdo_pgsql
, and returned structured JSON, everything clicked into place. Now I have a working Ajax form, secure inserts into Postgres, and a “recent submissions” list to confirm everything works. Most importantly, I gained the confidence to troubleshoot both JavaScript and PHP together instead of blaming one side.