shedeza / sybase-ase-orm-bundle
Symfony Bundle for Sybase ASE ORM
Installs: 4
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/shedeza/sybase-ase-orm-bundle
Requires
- php: ^8.1
- ext-pdo: *
- ext-pdo_dblib: *
- symfony/config: ^6.0|^7.0
- symfony/console: ^6.0|^7.0
- symfony/dependency-injection: ^6.0|^7.0
- symfony/framework-bundle: ^6.0|^7.0
Requires (Dev)
- phpunit/phpunit: ^9.0
README
Un Bundle de Symfony que implementa un Object-Relational Mapper (ORM) para Sybase ASE.
Características
- Mapeo de Entidades: Utiliza PHP Attributes para definir entidades y sus propiedades
- Entity Manager: Manejo de persistencia con métodos
persist(),remove(),flush() - Repositorios: Patrón Repository con métodos comunes (
find(),findAll(),findBy(), etc.) - Relaciones: Soporte completo para OneToOne, OneToMany, ManyToOne y ManyToMany con cascadas
- OQL: Lenguaje de consulta orientado a objetos
- Transacciones: Manejo automático de transacciones
- Lazy Loading: Carga perezosa de relaciones (implementación básica)
Instalación
composer require shedeza/sybase-ase-orm-bundle
Configuración
Agregar en config/bundles.php:
return [ // ... Shedeza\SybaseAseOrmBundle\SybaseAseOrmBundle::class => ['all' => true], ];
Configurar en config/packages/sybase_ase_orm.yaml:
sybase_ase_orm: default_connection: default default_entity_manager: default connections: default: '%env(resolve:DATABASE_SYBASE_URL)%' entity_managers: default: connection: default mappings: App: type: attribute dir: '%kernel.project_dir%/src/Entity' prefix: 'App\Entity'
Agregar en tu archivo .env:
# Format: sybase://username:password@host:port/database?charset=utf8 DATABASE_SYBASE_URL=sybase://sa:your_password@localhost:5000/mydb?charset=utf8
Configuración Alternativa (Detallada)
También puedes usar la configuración detallada:
sybase_ase_orm: connections: default: host: '%env(SYBASE_HOST)%' port: '%env(int:SYBASE_PORT)%' database: '%env(SYBASE_DATABASE)%' username: '%env(SYBASE_USERNAME)%' password: '%env(SYBASE_PASSWORD)%' charset: '%env(SYBASE_CHARSET)%'
Uso Básico
Definir una Entidad
Entidad con Llave Primaria Simple
<?php namespace App\Entity; use Shedeza\SybaseAseOrmBundle\ORM\Mapping as ORM; #[ORM\Entity] #[ORM\Table(name: 'users')] class User { #[ORM\Id] #[ORM\GeneratedValue(strategy: ORM\GeneratedValue::IDENTITY)] #[ORM\Column(type: 'integer')] private ?int $id = null; #[ORM\Column(type: 'string', length: 100)] private string $username; #[ORM\Column(type: 'string', length: 255)] private string $email; // getters y setters... }
Entidad con Llave Primaria Compuesta
<?php namespace App\Entity; use Shedeza\SybaseAseOrmBundle\ORM\Mapping as ORM; #[ORM\Entity] #[ORM\Table(name: 'user_roles')] class UserRole { #[ORM\Id] #[ORM\Column(type: 'integer')] private ?int $userId = null; #[ORM\Id] #[ORM\Column(type: 'integer')] private ?int $roleId = null; #[ORM\Column(type: 'datetime')] private ?\DateTime $assignedAt = null; // getters y setters... }
Usar el Entity Manager
<?php namespace App\Controller; use Shedeza\SybaseAseOrmBundle\ORM\EntityManager; use App\Entity\User; class UserController { public function create(EntityManager $entityManager): void { $user = new User(); $user->setUsername('john_doe'); $user->setEmail('john@example.com'); $entityManager->persist($user); $entityManager->flush(); } public function find(EntityManager $entityManager, int $id): ?User { return $entityManager->find(User::class, $id); } public function findComposite(EntityManager $entityManager): ?UserRole { // Buscar por llave primaria compuesta $compositeId = ['userId' => 1, 'roleId' => 2]; return $entityManager->find(UserRole::class, $compositeId); } }
Usar Repositorios
Repositorio Básico
<?php $repository = $entityManager->getRepository(User::class); // Buscar por ID $user = $repository->find(1); // Buscar todos $users = $repository->findAll(); // Buscar con criterios $users = $repository->findBy(['username' => 'john_doe']); // Buscar uno con criterios $user = $repository->findOneBy(['email' => 'john@example.com']);
Repositorios Personalizados
<?php namespace App\Repository; use Shedeza\SybaseAseOrmBundle\ORM\Repository\AbstractRepository; use App\Entity\User; class UserRepository extends AbstractRepository { public function findByUsername(string $username): ?User { $query = $this->createQuery('SELECT u FROM User u WHERE u.username = :username'); $query->setParameter('username', $username); return $query->getSingleResult(); } public function findActiveUsers(): array { $query = $this->createQuery('SELECT u FROM User u WHERE u.createdAt IS NOT NULL ORDER BY u.createdAt DESC'); return $query->getResult(); } }
Inyección Directa de Repositorios
<?php // Los repositorios se pueden inyectar directamente use App\Repository\UserRepository; class UserService { public function __construct( private UserRepository $userRepository ) {} public function getActiveUsers(): array { return $this->userRepository->findActiveUsers(); } }
<?php namespace App\Entity; use Shedeza\SybaseAseOrmBundle\ORM\Mapping as ORM; use App\Repository\UserRepository; #[ORM\Entity] #[ORM\Repository(repositoryClass: UserRepository::class)] #[ORM\Table(name: 'users')] class User { // ... }
Consultas OQL
Consultas Básicas
<?php $query = $entityManager->createQuery('SELECT u FROM User u WHERE u.username = :username'); $query->setParameter('username', 'john_doe'); $users = $query->getResult();
Consultas con JOINs
Sintaxis tradicional con ON
<?php // INNER JOIN $query = $entityManager->createQuery(' SELECT u FROM User u INNER JOIN Post p ON p.author = u.id WHERE p.title LIKE :title '); $query->setParameter('title', '%post%'); $users = $query->getResult(); // LEFT JOIN $query = $entityManager->createQuery(' SELECT u FROM User u LEFT JOIN Post p ON p.author = u.id ORDER BY u.username ASC '); $users = $query->getResult();
Sintaxis WITH (estilo Doctrine)
<?php // JOIN usando asociaciones definidas en entidades $query = $entityManager->createQuery(' SELECT u FROM User u INNER JOIN u.posts p ORDER BY u.username ASC '); $users = $query->getResult(); // JOIN con condiciones WITH $query = $entityManager->createQuery(' SELECT u FROM User u INNER JOIN u.posts p WITH p.title LIKE :title ORDER BY u.username ASC '); $query->setParameter('title', '%post%'); $users = $query->getResult(); // LEFT JOIN con WITH $query = $entityManager->createQuery(' SELECT p FROM Post p LEFT JOIN p.author u WITH u.email LIKE :domain ORDER BY p.id DESC '); $query->setParameter('domain', '%@example.com'); $posts = $query->getResult(); // JOINs anidados con WITH $query = $entityManager->createQuery(' SELECT p FROM Post p INNER JOIN p.author u WITH u.createdAt IS NOT NULL LEFT JOIN u.posts p2 WITH p2.id != p.id ORDER BY p.id DESC '); $posts = $query->getResult();
Relaciones
<?php #[ORM\Entity] class Post { #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'posts')] #[ORM\JoinColumn(name: 'author_id', referencedColumnName: 'id')] private ?User $author = null; } #[ORM\Entity] class User { #[ORM\OneToMany(targetEntity: Post::class, mappedBy: 'author')] private array $posts = []; }
Atributos Disponibles
Entidades y Tablas
#[ORM\Entity]: Marca una clase como entidad#[ORM\Repository(repositoryClass: MyRepository::class)]: Define repositorio personalizado#[ORM\Table(name: 'table_name')]: Define el nombre de la tabla#[ORM\Index(columns: ['field1', 'field2'])]: Define índices
Campos
#[ORM\Column(type: 'string', length: 255)]: Define una columna#[ORM\Id]: Marca una propiedad como identificador#[ORM\GeneratedValue]: Define estrategia de generación de ID
Relaciones
#[ORM\OneToOne]: Relación uno a uno#[ORM\OneToMany]: Relación uno a muchos#[ORM\ManyToOne]: Relación muchos a uno#[ORM\ManyToMany]: Relación muchos a muchos#[ORM\JoinColumn]: Define columna de unión#[ORM\JoinTable]: Define tabla de unión para ManyToMany
Eventos del Ciclo de Vida
#[ORM\PrePersist]: Ejecuta antes de persistir#[ORM\PostPersist]: Ejecuta después de persistir
Características Avanzadas
Manejo de Transacciones
<?php // Transacción manual $entityManager->getConnection()->beginTransaction(); try { $entityManager->persist($entity1); $entityManager->persist($entity2); $entityManager->flush(); $entityManager->getConnection()->commit(); } catch (\Exception $e) { $entityManager->getConnection()->rollback(); throw $e; } // Transacción automática $result = $entityManager->transactional(function($em) { $em->persist($entity1); $em->persist($entity2); return $entity1->getId(); });
Gestión del Ciclo de Vida
<?php // Limpiar todas las entidades del contexto $entityManager->clear(); // Desconectar una entidad específica $entityManager->detach($entity); // Limpiar cache de metadatos $entityManager->clearMetadataCache();
Logging de Consultas
<?php use Shedeza\SybaseAseOrmBundle\DBAL\Logger\QueryLogger; class MyQueryLogger implements QueryLogger { public function logQuery(string $sql, array $params = [], float $executionTime = 0.0): void { error_log("SQL: {$sql} - Time: {$executionTime}s"); } } $connection = new Connection($config, new MyQueryLogger());
Testing
# Ejecutar tests composer test # O directamente con PHPUnit vendor/bin/phpunit
Requisitos
- PHP 8.1+
- Symfony 6.0+ o 7.0+
- Extensión PDO_DBLIB
- Sybase ASE 15.0+
Optimizaciones Incluidas
- Cache de metadatos: Los metadatos de entidades se cachean automáticamente
- Cache de parsing OQL: Las consultas parseadas se cachean para mejor rendimiento
- Lazy loading: Carga perezosa de relaciones (implementación básica)
- Identity Map: Previene duplicación de objetos en memoria
- Transacciones optimizadas: Solo inicia transacciones cuando hay cambios pendientes
Contribuir
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/amazing-feature) - Commit tus cambios (
git commit -m 'Add amazing feature') - Push a la rama (
git push origin feature/amazing-feature) - Abre un Pull Request
Licencia
MIT