# Two Annoying Phalcon Errors and How to Fix Them: e_id and SoftDelete

> If you’re using Phalcon, you’ve probably fallen in love with its speed and flexibility. But let’s be real—sometimes it throws curveballs that make you question your life choices.

- Author: [Halit Yeşil](https://halityesil.com/en/)
- Published: 2025-07-27
- Language: English
- Canonical URL: https://halityesil.com/en/two-annoying-phalcon-errors-and-how-to-fix-them-e-id-and-softdelete/
- Turkish version: https://halityesil.com/phalconda-karsilastigim-iki-can-sikici-hata-ve-cozumleri-e-id-ve-softdelete.md
- Category: Phalcon, Survival Guide for Developers
- Tags: database deletion, e_id error, error resolution, pdo, phalcon, phalcon bypass softdelete, phalcon database delete issue, phalcon database management, phalcon developer guide, phalcon disable softdelete, phalcon e_id error fix, phalcon error debugging, phalcon model initialize issue, phalcon note_id error, phalcon note_id parsing error, phalcon pdo delete query, phalcon permanent delete method, phalcon phql query error, phalcon phql square brackets, phalcon softdelete permanent delete, php framework, phql, softdelete
- License: https://creativecommons.org/licenses/by-nc/4.0/
- Cite as: Halit Yeşil. “Two Annoying Phalcon Errors and How to Fix Them: e_id and SoftDelete”. halityesil.com, 2025-07-27. https://halityesil.com/en/two-annoying-phalcon-errors-and-how-to-fix-them-e-id-and-softdelete/

---

## Problem: What’s Going Wrong with Phalcon?

I ran into two particularly frustrating issues:

1. **The e\_id Error**: You write a query with a column like `note_id`, and Phalcon freaks out with a “Column 'e\_id' doesn't exist” error.
2. **SoftDelete Hard Delete Woes**: You’re using the `SoftDelete` behavior, but sometimes you need to *permanently* delete records. Phalcon’s model initialization and caching make this trickier than it should be.

Sound familiar? Let’s dive into why these issues are such a pain and how to fix them.

## Agitate: Why These Problems Drive You Nuts

### The e\_id Error

Imagine you’re querying your `NotesTranslations` model like this:

```php
$translation = NotesTranslations::findFirst([
    'conditions' => 'note_id = :noteId:',
    'bind' => ['noteId' => 123]
]);
```

And then, BOOM! You get this error:
`Column 'e_id' doesn't belong to any of the selected models`.
What’s going on? Phalcon’s PHQL engine mistakenly parses `note_id` as `not e_id`, treating `not` as an operator and `e_id` as a column. Spoiler alert: there’s no `e_id` in your database! You spend hours digging through stack traces, searching forums, and pulling your hair out because the solution is nowhere to be found. This error pops up whenever a column name contains something like `not`, and it’s a total productivity killer.

### The SoftDelete Problem

With `SoftDelete`, you mark records as deleted (e.g., setting `is_deleted = 1`) instead of removing them. But what if you need to *actually* delete a record—say, for a test environment or legal reasons? Phalcon’s `modelsManager` initializes models and caches their metadata on the first query, so disabling `SoftDelete` at runtime is nearly impossible. I tried everything:

- Adding a static `$disableSoftDelete` flag? Nope, the model’s already cached.
- Creating a child class with an empty `initialize`? Phalcon still uses the parent class.
- Writing raw PHQL queries? The model’s behaviors still kick in.

It’s like Phalcon is saying, “You chose soft delete, now live with it!” Meanwhile, your project deadlines are looming.

## Solution: Here’s How to Fix It

### 1. Fixing the e\_id Error

The fix for the `e_id` error is simple but clever: wrap column names in square brackets (`[]`) in PHQL queries. This tells Phalcon to treat the column name as a literal string. Here’s how:

```php
$translation = NotesTranslations::findFirst([
    'conditions' => '[note_id] = :noteId: AND [language_id] = :languageId:',
    'bind' => [
        'noteId' => 123,
        'languageId' => 1
    ]
]);
```

This tiny change stops Phalcon from misinterpreting `note_id` as `not e_id`. No more errors, and your query works like a charm! Note: This only applies to PHQL queries. If you’re using raw SQL with PDO, you don’t need the brackets.

**Pro Tip**: If your column names include other tricky words like `order` or `set`, always use `[column_name]` in PHQL to avoid similar issues.

### 2. Bypassing SoftDelete for Permanent Deletion

To permanently delete records while using `SoftDelete`, the most reliable solution is to bypass Phalcon’s model layer entirely and use PDO with raw SQL. Why? Because PHQL queries trigger model initialization, which brings `SoftDelete` back into play. Here’s how to do it:

#### Step 1: Raw SQL with PDO

Add a `deletePermanently` method to your `Notes` model:

```php
public function deletePermanently()
{
    $messages = [];
    $db = $this->getDI()->getDb(); // Get PDO connection

    try {

        $sql = "DELETE FROM notes WHERE id = :id";
        $stmt = $db->prepare($sql);
        $stmt->execute(['id' => $this->id]);
        error_log("Deleted {$stmt->rowCount()} rows from notes for id = {$this->id}");

        return [true, $messages];
    } catch (\PDOException $e) {
        $messages[] = "Database error: {$e->getMessage()}";
        error_log("Error in deletePermanently: {$e->getMessage()}");
        return [false, $messages];
    }
}
```

#### Step 2: Use It in the Controller

Call this method in your `NotesController`:

```php
public function deletePermanentlyAction()
{
    $json = $this->request->getJsonRawBody();

    if (!isset($json->noteId)) {
        return $this->response->setJsonContent([
            'status' => 'error',
            'success' => false,
            'error' => 'Note ID is required',
            'data' => []
        ]);
    }

    $note = Notes::findFirst([
        'conditions' => '[id] = :id:',
        'bind' => ['id' => (int)$json->noteId]
    ]);

    if (!$note) {
        return $this->response->setJsonContent([
            'status' => 'error',
            'success' => false,
            'error' => 'Note not found',
            'data' => []
        ]);
    }

    try {
        [$success, $messages] = $note->deletePermanently();
        if (!$success) {
            return $this->response->setJsonContent([
                'status' => 'error',
                'success' => false,
                'error' => $messages ?: ['Failed to delete permanently'],
                'data' => []
            ]);
        }
    } catch (\Exception $e) {
        return $this->response->setJsonContent([
            'status' => 'error',
            'success' => false,
            'error' => $e->getMessage(),
            'data' => []
        ]);
    }

    return $this->response->setJsonContent([
        'status' => 'success',
        'success' => true,
        'error' => null,
        'data' => []
    ]);
}
```

#### Step 3: Debug Like a Pro

If the deletion fails, check for database constraints:

```php
SHOW CREATE TABLE notes_translations;
```

If there’s a foreign key without `ON DELETE CASCADE`, the code above handles it by deleting related records first.

**Pro Tip**: Log the number of affected rows (`$stmt->rowCount()`) to confirm which tables are being modified. This makes debugging a breeze.

## Final Thoughts

Phalcon is a beast of a framework, but these quirks can trip up even seasoned developers. Fixing the `e_id` error with `[note_id]` and bypassing `SoftDelete` with PDO will save you hours of frustration. Hopefully, these solutions make your Phalcon projects smoother! If you hit another Phalcon roadblock, check my blog or drop me a line—we’ll figure it out together!
