PHPackages                             tetthys/sql-view - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. tetthys/sql-view

ActiveLibrary[Database &amp; ORM](/categories/database)

tetthys/sql-view
================

Framework-agnostic SQL view base with optional Laravel adapter (PHP 8.3+).

0.0.7(7mo ago)042MITPHPPHP ^8.3

Since Oct 20Pushed 7mo agoCompare

[ Source](https://github.com/tetthys/sql-view)[ Packagist](https://packagist.org/packages/tetthys/sql-view)[ RSS](/packages/tetthys-sql-view/feed)WikiDiscussions dev Synced 1mo ago

READMEChangelog (7)DependenciesVersions (8)Used By (0)

tetthys/sql-view
================

[](#tetthyssql-view)

A **framework-agnostic SQL view base** with an optional **Laravel adapter**, written for **PHP 8.3+**.

This library lets you define SQL views as small PHP classes backed by `.sql` files,
so you can create, refresh, drop, and inspect database views from code or migrations.
It also provides a lightweight **Eloquent ViewModel** for read-only access to those views.

---

🧱 Installation
--------------

[](#-installation)

```
composer require tetthys/sql-view
```

If you use Laravel, the adapter and Eloquent integration will work automatically — no service provider required.

---

⚙️ Structure
------------

[](#️-structure)

```
sql-view/
├─ src/
│  ├─ AbstractSqlView.php       # Framework-independent core
│  ├─ Adapter/
│  │  └─ LaravelSqlView.php     # Laravel adapter (auto-wires DB::unprepared)
│  ├─ Eloquent/
│  │  └─ ViewModel.php          # Read-only Eloquent base for SQL VIEWs
│  └─ Support/
│     └─ SqlHelper.php          # Identifier quoting, param substitution

```

---

🚀 Usage
-------

[](#-usage)

### ✅ 1. Framework-independent (pure PHP)

[](#-1-framework-independent-pure-php)

```
use Tetthys\SqlView\AbstractSqlView;

final class DemoView extends AbstractSqlView
{
    protected const string NAME = 'demo_view';
    protected const string SQL_FILE = __DIR__ . '/sql/demo_view.sql';
    protected static array $params = ['active' => 1];
}

// Inject any executor (e.g., PDO)
DemoView::setExecutor(fn(string $sql) => $pdo->exec($sql));

// Create or refresh the view
DemoView::ensureExists();
```

---

### ✅ 2. Laravel adapter

[](#-2-laravel-adapter)

```
use Tetthys\SqlView\Adapter\LaravelSqlView;

final class ProductCardView extends LaravelSqlView
{
    protected const string NAME = 'product_card';
    protected const string SQL_FILE = 'resources/sql/product_card_view.sql';
    protected static array $params = ['deletedFlag' => 0];
}

// Inside Laravel (DB::unprepared auto-wired)
ProductCardView::refresh();
```

**Example SQL file (`resources/sql/product_card_view.sql`):**

```
CREATE OR REPLACE VIEW `product_card` AS
SELECT id, title, price
FROM products
WHERE deleted = :deletedFlag;
```

---

### ✅ 3. Read-only Eloquent ViewModel

[](#-3-read-only-eloquent-viewmodel)

```
use Tetthys\SqlView\Eloquent\ViewModel;
use App\SqlViews\ProductCardView;

final class ProductCard extends ViewModel
{
    protected $table = 'product_card';
}
```

Now you can query your SQL view safely:

```
use App\Models\ProductCard;

// Query like any Eloquent model
$rows = ProductCard::query()
    ->where('price', '>', 1000)
    ->orderByDesc('price')
    ->limit(10)
    ->get();

// Read-only protection
ProductCard::first()?->delete(); // ❌ LogicException
```

---

🧩 Laravel-specific helper methods
---------------------------------

[](#-laravel-specific-helper-methods)

MethodDescription`ensureExists()`Create or replace the view`refresh()`Drop and recreate the view`drop()`Drop the view if it exists`exists()`Check whether the view exists`query()`Return a `DB::table()` builder for the view`all()`Return all rows as a `Collection``dumpSql()`Read SQL file with parameter substitution`explain()`Run `EXPLAIN SELECT * FROM view` (MySQL only)`count()`Return `count(*)` from the view**Example:**

```
if (!ProductCardView::exists()) {
    ProductCardView::ensureExists();
}

$count = ProductCardView::count();
$rows  = ProductCardView::query()->where('price', '>', 1000)->get();

dump(ProductCardView::dumpSql());
```

---

🧠 ViewModel helper methods
--------------------------

[](#-viewmodel-helper-methods)

MethodDescription`rowsCount()`Count total rows`columns()`Get column names`isView()`Verify that the table is a VIEW`tableExists()`Check if the underlying view/table exists`allRows()`Fetch all rows as a `Collection``chunkReadOnly($size, $callback)`Iterate chunks safely`eachReadOnly($size)`Lazy generator iteration---

🧩 Typical Laravel integration
-----------------------------

[](#-typical-laravel-integration)

**Migration**

```
use Illuminate\Database\Migrations\Migration;
use App\SqlViews\ProductCardView;

return new class extends Migration {
    public function up(): void { ProductCardView::ensureExists(); }
    public function down(): void { ProductCardView::drop(); }
};
```

**Model**

```
use App\Models\ProductCard;

ProductCard::rowsCount();      // Count rows
ProductCard::columns();        // Get column names
ProductCard::chunkReadOnly(50, fn($chunk) => ...);
```

---

🧠 Notes
-------

[](#-notes)

- Placeholder replacement is simple string substitution (`:key` → value). For escaping or complex templating, override `sql()` in your subclass.
- Works with any SQL dialect supporting `CREATE OR REPLACE VIEW` and `DROP VIEW`.
- `ViewModel` offers a safe, fully read-only Eloquent interface.
- No service provider or configuration required.

---

⚖️ License
----------

[](#️-license)

MIT © Tetthys

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance65

Regular maintenance activity

Popularity8

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

7

Last Release

210d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/858f92afec0ff81e6888c9ae6f363b56ebf82e45a32d9e1b37341569c5d1b267?d=identicon)[tetthys](/maintainers/tetthys)

### Embed Badge

![Health badge](/badges/tetthys-sql-view/health.svg)

```
[![Health](https://phpackages.com/badges/tetthys-sql-view/health.svg)](https://phpackages.com/packages/tetthys-sql-view)
```

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90440.3M211](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)[wildside/userstamps

Laravel Userstamps provides an Eloquent trait which automatically maintains `created\_by` and `updated\_by` columns on your model, populated by the currently authenticated user in your application.

7511.7M13](/packages/wildside-userstamps)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
