1. Go to this page and download the library: Download methorz/swift-db library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
declare(strict_types=1);
namespace App\Domain\Entity;
use MethorZ\SwiftDb\Entity\AbstractEntity;
use MethorZ\SwiftDb\Trait\TimestampsTrait;
use MethorZ\SwiftDb\Trait\UuidTrait;
use DateTimeImmutable;
class Product extends AbstractEntity
{
use TimestampsTrait;
use UuidTrait;
public ?int $id = null;
public string $name = '';
public float $price = 0.0;
public int $stock = 0;
public static function getTableName(): string
{
return 'product';
}
public function getColumnMapping(): array
{
return [
'id' => 'product_id',
'name' => 'product_name',
'price' => 'product_price',
'stock' => 'product_stock',
...$this->getTimestampMapping(),
...$this->getUuidMapping(),
];
}
}
declare(strict_types=1);
namespace App\Infrastructure\Repository;
use App\Domain\Entity\Product;
use MethorZ\SwiftDb\Repository\AbstractRepository;
/**
* @extends AbstractRepository<Product>
*/
class ProductRepository extends AbstractRepository
{
public function getTableName(): string
{
return 'product';
}
public function getEntityClass(): string
{
return Product::class;
}
/**
* Find products by category with price range
*
* @return array<Product>
*/
public function findByCategory(int $categoryId, float $minPrice, float $maxPrice): array
{
$rows = $this->query()
->where('product_category_id', $categoryId)
->whereBetween('product_price', $minPrice, $maxPrice)
->orderBy('product_price', 'ASC')
->get();
return array_map(fn (array $row) => $this->hydrateEntity($row), $rows);
}
}
// Get repository from container
$repository = $container->get(ProductRepository::class);
// Create and save
$product = $repository->create();
$product->name = 'Widget';
$product->price = 29.99;
$product->stock = 100;
$repository->save($product);
// Find
$product = $repository->find(1);
$product = $repository->findOrFail(1); // Throws if not found
// Update
$product->price = 24.99;
$repository->save($product); // Only updates changed fields
// Delete
$repository->delete($product);
// or
$repository->deleteById(1);
// Query builder
$products = $repository->query()
->where('product_price', '>', 10)
->whereNotNull('product_stock')
->orderBy('product_created', 'DESC')
->limit(10)
->get();
// Simple pagination
$result = $repository->paginate(perPage: 15, page: 1);
// Access items
foreach ($result as $row) {
echo $row['product_name'];
}
// Or use items property
$items = $result->items;
// Pagination metadata
$result->total; // Total records
$result->perPage; // Items per page
$result->currentPage; // Current page number
$result->lastPage(); // Last page number
$result->hasMorePages(); // Has next page?
$result->hasPreviousPage(); // Has previous page?
// SPL interfaces
count($result); // Returns total (Countable)
foreach ($result as $row) { // Iterates items (IteratorAggregate)
// ...
}
// With query conditions
$result = $repository->query()
->where('active', true)
->orderBy('created_at', 'DESC')
->paginate(20, 2);
// Manual
$repository->beginTransaction();
try {
$repository->save($product1);
$repository->save($product2);
$repository->commit();
} catch (\Throwable $e) {
$repository->rollback();
throw $e;
}
// Or use the helper
$repository->transaction(function () use ($repository, $product1, $product2) {
$repository->save($product1);
$repository->save($product2);
});
use MethorZ\SwiftDb\Trait\VersionTrait;
class Product extends AbstractEntity
{
use VersionTrait;
// ...
public function getColumnMapping(): array
{
return [
// ...
...$this->getVersionMapping(),
];
}
}
// Now updates will check the version
try {
$repository->save($product);
} catch (OptimisticLockException $e) {
// Entity was modified by another process
}
// Implicit equals (Laravel-style)
$rows = $this->query()
->where('product_active', true)
->where('product_category_id', $categoryId)
->get();
// Array syntax
$rows = $this->query()
->where([
'product_active' => true,
'product_status' => 'published',
])
->get();
// Nested conditions (AND with OR inside)
// WHERE active = 1 AND (price < 10 OR featured = 1)
$rows = $this->query()
->where('product_active', true)
->where(function ($q) {
$q->where('product_price', '<', 10)
->orWhere('product_featured', true);
})
->get();
// Conditional building
$rows = $this->query()
->where('product_active', true)
->when($categoryId, fn($q, $id) => $q->where('product_category_id', $id))
->when($minPrice, fn($q, $min) => $q->where('product_price', '>=', $min))
->get();
// Join with conditions
$rows = $this->query()
->leftJoin('discount', function ($join) use ($today) {
$join->on('product.product_id', 'discount.discount_product_id')
->where('discount.discount_active', true)
->where('discount.discount_start', '<=', $today);
})
->get();
// Subquery in whereIn
$rows = $this->query()
->whereIn('product_category_id', function ($sub) {
$sub->table('category')
->select('category_id')
->where('category_active', true);
})
->get();
// EXISTS subquery
$rows = $this->query()
->whereExists(function ($sub) {
$sub->table('inventory')
->select('1')
->whereColumn('inventory.product_id', 'product.product_id')
->where('inventory.quantity', '>', 0);
})
->get();
// OR convenience methods - Multi-field search
// WHERE active = 1 AND (name LIKE ? OR sku LIKE ?)
$rows = $this->query()
->where('product_active', true)
->where(function ($q) use ($searchTerm) {
$q->whereLike('product_name', "%{$searchTerm}%")
->orWhereLike('product_sku', "%{$searchTerm}%");
})
->get();
// OR BETWEEN - Price range or high stock
// WHERE (price BETWEEN 10 AND 50) OR (stock BETWEEN 100 AND 500)
$rows = $this->query()
->whereBetween('product_price', 10.0, 50.0)
->orWhereBetween('product_stock', 100, 500)
->get();
// OR NOT BETWEEN - Exclude middle range
// WHERE price NOT BETWEEN 50 AND 100 OR stock NOT BETWEEN 10 AND 50
$rows = $this->query()
->whereNotBetween('product_price', 50.0, 100.0)
->orWhereNotBetween('product_stock', 10, 50)
->get();
// OR IN - Multiple category sets
// WHERE category_id IN (1, 2) OR status IN ('active', 'featured')
$rows = $this->query()
->whereIn('product_category_id', [1, 2])
->orWhereIn('product_status', ['active', 'featured'])
->get();
// OR NOT IN - Exclude multiple sets
// WHERE status NOT IN ('deleted', 'archived') OR category_id NOT IN (5, 6)
$rows = $this->query()
->whereNotIn('product_status', ['deleted', 'archived'])
->orWhereNotIn('product_category_id', [5, 6])
->get();
// OR IN with subquery - Active categories OR featured tags
$rows = $this->query()
->whereIn('product_category_id', function ($sub) {
$sub->table('category')->select('category_id')->where('category_active', true);
})
->orWhereIn('product_tag_id', function ($sub) {
$sub->table('tag')->select('tag_id')->where('tag_featured', true);
})
->get();
// OR EXISTS - Has inventory OR has pre-orders
$rows = $this->query()
->whereExists(function ($sub) {
$sub->table('inventory')
->select('1')
->whereColumn('inventory.product_id', 'product.product_id')
->where('inventory.quantity', '>', 0);
})
->orWhereExists(function ($sub) {
$sub->table('pre_order')
->select('1')
->whereColumn('pre_order.product_id', 'product.product_id');
})
->get();
// OR NOT EXISTS - No reviews OR no ratings
$rows = $this->query()
->whereNotExists(function ($sub) {
$sub->table('review')->select('1')->whereColumn('review.product_id', 'product.product_id');
})
->orWhereNotExists(function ($sub) {
$sub->table('rating')->select('1')->whereColumn('rating.product_id', 'product.product_id');
})
->get();
// OR RAW - Complex business logic
// WHERE margin > 20 OR (price * discount_multiplier) < cost
$rows = $this->query()
->whereRaw('(product_price - product_cost) / product_price > ?', [0.2])
->orWhereRaw('product_price * ? < product_cost', [0.8])
->get();
$this->query()
->leftJoin('discount', function (JoinClause $join) use ($today) {
$join->on('product.product_id', 'discount.product_id')
->where('discount.active', true)
->where('discount.start_date', '<=', $today)
->whereNull('discount.deleted_at');
})
->get();
use MethorZ\SwiftDb\Query\QueryLogger;
// Create with PSR-3 logger (optional)
$logger = new QueryLogger($psrLogger);
// Pass to repository/query builder
$repository = new ProductRepository($connection, $logger);
// After some operations...
$summary = $logger->getSummary();
// ['count' => 5, 'total_time_ms' => 12.5, 'avg_time_ms' => 2.5, 'slowest_ms' => 5.2]
// Find slow queries (> 100ms)
$slowQueries = $logger->getSlowQueries(0.1);
// Clear for next request
$logger->clear();
use MethorZ\SwiftDb\Cache\MappingCache;
// Configure with cache directory
$cache = new MappingCache('data/cache/database');
// First call: builds mapping via reflection, stores as PHP file
$mapping = $cache->getMapping(Product::class);
// Subsequent calls: loads from OPcache (fast!)
$mapping = $cache->getMapping(Product::class);
// Clear cache after entity changes (e.g., in deployment)
$cache->clear();
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.