composer require zjkiza/sql-blade
config/view.php under the paths key:
'paths' => [
resource_path('sql'),
app_path('Sql'),
],
app/Sql/User/select_user.blade.sql) with Blade syntax:
SELECT * FROM users WHERE id = :id;
SqlBladeInterface via constructor and run:
$result = $this->sqlBlade->executeQuery('User.select_user', ['id' => 1]);
Fetch results using Doctrine DBAL methods:
$rows = $result->fetchAllAssociative();
Dynamic Query Building:
Use Blade directives (@if, @isset, @foreach) to conditionally include clauses:
SELECT * FROM users
@if($activeOnly)
WHERE active = 1
@endif
LIMIT :limit;
Execute with:
$this->sqlBlade->executeQuery('User.filter_users', [
'activeOnly' => true,
'limit' => 10,
]);
Transaction Management: Wrap multiple queries in a transaction:
$this->sqlBlade->transaction(function ($sqlBlade) {
$sqlBlade->executeQuery('User.create_user', ['name' => 'John']);
$sqlBlade->executeQuery('User.log_action', ['user_id' => 1, 'action' => 'created']);
});
Parameter Binding:
Bind parameters via the second argument of executeQuery:
INSERT INTO users (name, email) VALUES (:name, :email);
$this->sqlBlade->executeQuery('User.create_user', [
'name' => 'Jane',
'email' => 'jane@example.com',
]);
Reusable Components:
Store complex queries in separate files (e.g., app/Sql/Common/paginate.blade.sql) and include them:
@include('Common.paginate', ['limit' => 10, 'offset' => 0])
SqlBladeInterface in unit tests to isolate query logic:
$this->mock(SqlBladeInterface::class)->shouldReceive('executeQuery')->once();
Semicolon Requirement:
Forgetting ; at the end of SQL files causes silent failures. Validate files with:
grep -L ';$' app/Sql/*.sql
Path Configuration:
Misconfigured config/view.php paths lead to FileNotFoundException. Verify paths with:
$this->sqlBlade->getQueryPaths(); // Debug paths
Parameter Binding:
Unbound parameters (e.g., :missing_param) throw ParameterNotFoundException. Validate inputs before execution.
Blade Parsing Quirks:
@ symbols in SQL comments (e.g., -- @todo). Use -- or /* */ instead.@foreach inside @if) may require explicit escaping.Query Dumping:
Enable SQL logging in config/database.php:
'logging' => true,
Check Laravel logs for raw SQL after execution.
Result Inspection: Use Doctrine DBAL’s debug methods:
$result->columnCount(); // Check column count
$result->fetchNumeric(); // Inspect first row
Custom Directives: Extend Blade syntax by registering custom directives in a service provider:
Blade::directive('sqlif', function ($expression) {
return "<?php if({$expression}): ?>";
});
Usage in .blade.sql:
@sqlif($condition)
SELECT * FROM table
@endif
Query Preprocessing:
Override Zjk\SqlBlade\Services\SqlBlade to modify queries before execution (e.g., add logging):
public function executeQuery(string $queryName, array $params = []): Result
{
$this->logQuery($queryName, $params);
return parent::executeQuery($queryName, $params);
}
Result Transformation: Chain Doctrine DBAL result methods or create a decorator:
$result = $this->sqlBlade->executeQuery('User.get_all');
$users = $result->fetchAllAssociative();
$mapped = collect($users)->map(fn($u) => new UserModel($u));
How can I help you explore Laravel packages today?