Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Table Laravel Package

atlas/table

Atlas.Table is a table data gateway for Atlas, providing a clean API to interact with database tables. Built to support Atlas.Mapper but usable on its own, it helps you run queries and persist table rows with a focused, lightweight design.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require atlas/table
    

    Ensure your project uses Atlas (e.g., atlasphp/atlas or atlasphp/atlas-mapper) for connection management.

  2. Define a Table Class: Extend Atlas\Table\Table and configure it for your database table:

    use Atlas\Table\Table;
    
    class UserTable extends Table
    {
        protected $table = 'users';
        protected $primaryKey = 'id';
        protected $columns = ['id', 'name', 'email', 'is_active'];
    }
    
  3. First Use Case: Fetch a Row

    $userTable = new UserTable();
    $user = $userTable->fetchRow(1); // Fetches row with id=1
    echo $user->name; // Access columns directly
    
  4. Key Entry Points:

    • CRUD: fetchRow(), fetchRows(), insert(), update(), delete().
    • Events: Override TableEvents for hooks (e.g., beforeInsertRow()).
    • Rows: Use Row objects for column iteration (foreach ($row as $column => $value)).

Implementation Patterns

Core Workflows

  1. Row Operations:

    • Create/Update:
      $row = $userTable->newRow(['name' => 'John', 'email' => 'john@example.com']);
      $row->is_active = true;
      $userTable->insert($row); // Triggers beforeInsertRow() event
      
    • Bulk Insert:
      $rows = [$userTable->newRow(['name' => 'Alice']), ...];
      $userTable->insertRows($rows);
      
  2. Querying:

    • Basic Select:
      $users = $userTable->select()->where('is_active', true)->fetchRows();
      
    • Custom Select:
      $select = new Atlas\Table\Select();
      $select->from($userTable->getTable())
             ->where('name', 'LIKE', '%ohn%');
      $users = $userTable->selectRows($select);
      
  3. Event-Driven Logic:

    • Custom Events Class:
      use Atlas\Table\TableEvents;
      
      class UserTableEvents implements TableEvents
      {
          public function beforeInsertRow($row): ?array
          {
              if (empty($row->email)) {
                  throw new \InvalidArgumentException('Email is required');
              }
              return $row->getArrayCopy(); // Return null to use default values
          }
      }
      
    • Attach Events:
      $userTable->setEvents(new UserTableEvents());
      
  4. Row Iteration:

    foreach ($user as $column => $value) {
        echo "$column: $value\n";
    }
    // Or check modifications:
    if ($user->isModified()) {
        $userTable->update($user);
    }
    

Integration Tips

  • Laravel Database Connections: Use Atlas’s ConnectionLocator to bridge Laravel’s DB facade:

    $locator = new Atlas\ConnectionLocator();
    $locator->addConnection('mysql', \DB::connection('mysql')->getPdo());
    $userTable->setConnectionLocator($locator);
    
  • Composite Primary Keys: Override getPrimaryKey() in your table class if using composite keys:

    protected function getPrimaryKey(): array
    {
        return ['user_id', 'role_id'];
    }
    
  • Type-Safe Selects: Leverage _TableSelect classes for IDE autocompletion:

    /** @var UserTableSelect */
    $select = $userTable->select();
    

Gotchas and Tips

Pitfalls

  1. Primary Key Dependency:

    • Methods like updateRowPerform() and deleteRowPerform() throw exceptions if no primary key is defined (v1.4.0+).
    • Workaround: Define $primaryKey or override getPrimaryKey().
  2. Boolean Comparison Quirks:

    • Row::isModified() treats 1/0 as equivalent to true/false (v1.3.0+), but MySQL may still flag updates if the column is TINYINT(1).
    • Fix: Cast values explicitly:
      $row->is_active = (bool)$row->is_active;
      
  3. Event Hook Signatures:

    • Pre-insert/update hooks must return ?array (v1.0.0-beta4+). Return null to use default values.
    • BC Break: Older code using void return types will fail.
  4. Identifier Quoting:

    • Automatic quoting (v1.2.0+) may cause issues with reserved keywords (e.g., order). Use backticks explicitly:
      $select->from('`order`');
      
  5. Row Validation:

    • Row::assertValidValue() runs on construction, not assignment. To validate after changes:
      $row->name = 'New Name';
      $row->assertValidValue('name'); // Manual validation
      

Debugging Tips

  1. Query Logging: Enable Atlas’s query logging via ConnectionLocator:

    $locator->setLogger(new \Atlas\Logger\QueryLogger());
    
  2. Row Diffs: Use getArrayDiff() to debug updates:

    print_r($row->getArrayDiff()); // Shows modified columns
    
  3. Event Debugging: Dump event payloads:

    public function beforeInsertRow($row): ?array
    {
        \Log::debug('Inserting:', $row->getArrayCopy());
        return $row->getArrayCopy();
    }
    

Extension Points

  1. Custom Row Classes: Extend Atlas\Table\Row to add domain logic:

    class UserRow extends \Atlas\Table\Row
    {
        public function getFullName(): string
        {
            return "{$this->first_name} {$this->last_name}";
        }
    }
    

    Override Table::newRow() to return your class:

    protected function newRow(array $data = []): UserRow
    {
        return new UserRow($this, $data);
    }
    
  2. Dynamic Columns: Use getColumns() to fetch columns dynamically (e.g., from DB schema):

    protected function getColumns(): array
    {
        return $this->getConnection()->fetchColumnNames($this->table);
    }
    
  3. Bulk Operations: Optimize bulk inserts/updates by batching rows:

    $batch = [];
    foreach ($users as $user) {
        $batch[] = $user->getArrayCopy();
        if (count($batch) >= 100) {
            $userTable->insertRows($batch);
            $batch = [];
        }
    }
    

Laravel-Specific Quirks

  • No Eloquent Integration: Avoid mixing with Eloquent models. Use raw queries or Atlas.Mapper for hybrid setups.

  • Migration Conflicts: Atlas.Table assumes manual schema management. Use Laravel Migrations for schema changes, then sync with Atlas’s table definitions.

  • Testing: Mock TableLocator and ConnectionLocator for unit tests:

    $locator = $this->createMock(\Atlas\ConnectionLocator::class);
    $locator->method('getConnection')->willReturn($pdo);
    $userTable->setConnectionLocator($locator);
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky