Skip to content

A lightweight, easy-to-use Object-Relational Mapping (ORM) library for PHP that provides an elegant Active Record implementation for working with databases. Built with modern PHP practices including Composer autoloading and Docker support.

Notifications You must be signed in to change notification settings

realedwardgough/php-orm-kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Simple PHP ORM

A lightweight, easy-to-use Object-Relational Mapping (ORM) library for PHP that provides an elegant Active Record implementation for working with databases. Built with modern PHP practices including Composer autoloading and Docker support.

Features

  • πŸš€ Lightweight: Minimal overhead with maximum functionality
  • πŸ”„ Active Record Pattern: Intuitive database operations
  • πŸ” Query Builder: Fluent interface for complex queries
  • πŸ›‘οΈ Mass Assignment Protection: Secure attribute filling
  • πŸ” Hidden Attributes: Exclude sensitive data from output
  • πŸ“Š Automatic Table Names: Convention over configuration
  • 🐳 Docker Ready: Complete development environment
  • πŸ“¦ Composer Integration: PSR-4 autoloading
  • πŸ—οΈ Modern PHP: Follows current best practices
  • πŸ’Ύ Connection Management: Singleton database connections

Requirements

  • PHP 8.0 or higher
  • PDO MySQL extension
  • Composer
  • Docker & Docker Compose (for development environment)

Installation

Option 1: Using Docker (Recommended)

  1. Clone the repository:
git clone <repository-url>
cd simple-php-orm
  1. Copy environment file:
cp .env.example .env
  1. Start the Docker environment:
docker-compose up -d
  1. Install dependencies:
docker-compose exec app composer install
  1. Access the application:

Option 2: Local Installation

  1. Clone the repository
  2. Install dependencies:
composer install
  1. Configure your database in .env
  2. Include the autoloader in your application:
require_once 'vendor/autoload.php';

Project Structure

β”œβ”€β”€ db/                           # Database classes
β”‚   β”œβ”€β”€ Builder.php              # Query builder
β”‚   └── Connection.php           # Database connection
β”œβ”€β”€ public/                      # Web accessible files
β”‚   └── example.php             # Usage examples
β”œβ”€β”€ src/                        # Source code
β”‚   └── models/
β”‚       β”œβ”€β”€ Model.php           # Base model class
β”‚       β”œβ”€β”€ User.php            # User model example
β”‚       └── Post.php            # Post model example
β”œβ”€β”€ vendor/                     # Composer dependencies
β”œβ”€β”€ .env                       # Environment variables
β”œβ”€β”€ .dockerignore              # Docker ignore file
β”œβ”€β”€ 000-default.conf           # Apache configuration
β”œβ”€β”€ composer.json              # Composer configuration
β”œβ”€β”€ docker-compose.yml         # Docker services
β”œβ”€β”€ Dockerfile                 # Docker image definition
└── README.md                  # This file

Quick Start

1. Environment Setup

The .env file contains your environment configuration:

DB_HOST=mysql
DB_PORT=your_port
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

2. Database Configuration

The database configuration is handled automatically through environment variables in your .env file. The Connection class uses the vlucas/phpdotenv package to load these variables:

// Environment variables loaded automatically
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

3. Initialize in Your Application

<?php
require_once dirname(__DIR__).'/vendor/autoload.php';

use Database\Connection;
use Source\Models\User;
use Source\Models\Post;

// Initialize database connection
Connection::init();

4. Create Your First Model

<?php
namespace Source\Models;

class User extends Model
{
    protected static $table = 'users';
    protected static $fillable = ['name', 'email', 'password'];
    protected static $hidden = ['password'];
}

5. Start Using!

// Create a user
$user = User::create([
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'password' => 'secret123'
]);

// Find a user
$user = User::find(1);

// Update a user
$user->name = 'Jane Doe';
$user->save();

Docker Development Environment

Services

The Docker setup includes:

  • PHP 8.1 with Apache: Web server
  • MySQL 8.0: Database server
  • phpMyAdmin: Database management (http://localhost:8081)

Docker Commands

# Start services
docker-compose up -d

# Stop services
docker-compose down

# View logs
docker-compose logs app

# Execute commands in container
docker-compose exec app bash
docker-compose exec app composer install

# Database access
docker-compose exec mysql mysql -u root -p

File Permissions

If you encounter permission issues:

# Fix ownership (Linux/Mac)
sudo chown -R $USER:$USER .

# Or run in Docker
docker-compose exec app chown -R www-data:www-data /var/www/html

Composer Configuration

The composer.json includes PSR-4 autoloading:

{
  "name": "your-username/simple-php-orm",
  "description": "A lightweight PHP ORM",
  "autoload": {
    "psr-4": {
      "Database\\": "db/",
      "Source\\": "src/"
    }
  },
  "require": {
    "php": ">=8.0",
    "vlucas/phpdotenv": "^5.0"
  },
  "require-dev": {
    "phpunit/phpunit": "^9.0"
  }
}

Adding Dependencies

# Add a package
docker-compose exec app composer require package/name

# Add dev dependency
docker-compose exec app composer require --dev package/name

# Update dependencies
docker-compose exec app composer update

Usage Examples

Basic CRUD Operations

<?php
require_once dirname(__DIR__).'/vendor/autoload.php';

use Database\Connection;
use Source\Models\User;

Connection::init();

// Create
$user = User::create([
    'name' => 'John Doe',
    'email' => 'john@example.com'
]);

// Read
$user = User::find(1);
$users = User::all();

// Update
$user->name = 'Jane Doe';
$user->save();

// Delete
$user->delete();

Advanced Queries

use Database\Builder;
use Source\Models\User;

// Complex query with Builder
$activeUsers = User::get(
    User::query()
        ->where('status', 'active')
        ->where('email', 'LIKE', '%@company.com')
        ->orderBy('created_at', 'DESC')
        ->limit(10)
);

// Join queries
$usersWithPosts = User::get(
    User::query()
        ->select(['users.*', 'COUNT(posts.id) as post_count'])
        ->leftJoin('posts', 'users.id', 'posts.user_id')
        ->groupBy('users.id')
        ->having('post_count', '>', 0)
);

Model Relationships

<?php
namespace Source\Models;

class User extends Model
{
    protected static $fillable = ['name', 'email', 'password'];
    protected static $hidden = ['password'];

    public function posts()
    {
        return Post::get(
            Post::query()->where('user_id', $this->id)
        );
    }

    public static function findByEmail($email)
    {
        return static::findBy('email', $email);
    }
}

class Post extends Model
{
    protected static $fillable = ['title', 'content', 'user_id'];

    public function user()
    {
        return User::find($this->user_id);
    }
}

Configuration

Environment Variables

Set these in your .env file:

# Database Configuration
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=orm_database
DB_USERNAME=orm_user
DB_PASSWORD=secure_password

# Application
APP_ENV=development
APP_DEBUG=true

# Docker MySQL
MYSQL_ROOT_PASSWORD=root_password
MYSQL_DATABASE=orm_database
MYSQL_USER=orm_user
MYSQL_PASSWORD=secure_password

Database Configuration

The database connection is automatically configured using environment variables. The Database\Connection class uses the vlucas/phpdotenv package to load configuration from your .env file:

<?php
// Inside Database\Connection class
private function __construct()
{
    // Handle PDO options
    $config = [
        'options' => [
            \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
            \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
            \PDO::ATTR_EMULATE_PREPARES => false,
        ]
    ];

    // Load environment variables
    Dotenv::createImmutable(dirname(__DIR__))->load();

    // Build DSN and create connection
    $dsn = "mysql:host={$_ENV['DB_HOST']};port={$_ENV['DB_PORT']};dbname={$_ENV['DB_DATABASE']};charset=utf8mb4";
    $this->pdo = new \PDO($dsn, $_ENV['DB_USERNAME'], $_ENV['DB_PASSWORD'], $config['options']);
}

Required environment variables in your .env file:

DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

Testing

Running Tests

# Install dev dependencies
docker-compose exec app composer install

# Run tests
docker-compose exec app ./vendor/bin/phpunit

# Run with coverage
docker-compose exec app ./vendor/bin/phpunit --coverage-html coverage

Creating Tests

<?php
use PHPUnit\Framework\TestCase;
use Source\Models\User;

class UserTest extends TestCase
{
    public function testUserCreation()
    {
        $user = User::create([
            'name' => 'Test User',
            'email' => 'test@example.com'
        ]);

        $this->assertInstanceOf(User::class, $user);
        $this->assertEquals('Test User', $user->name);
    }
}

Production Deployment

Environment Setup

  1. Set production environment variables
  2. Configure web server (Apache/Nginx)
  3. Set proper file permissions
  4. Enable PHP OPcache
  5. Use environment-specific configuration

Security Considerations

// Always validate input
$userData = filter_var_array($_POST, [
    'name' => FILTER_SANITIZE_STRING,
    'email' => FILTER_VALIDATE_EMAIL
]);

// Use prepared statements (built-in)
$users = User::get(
    User::query()->where('email', $email) // Automatically uses prepared statements
);

// Hash passwords properly
class User extends Model
{
    public function setPassword($password)
    {
        $this->password = password_hash($password, PASSWORD_DEFAULT);
    }
}

API Reference

Connection Class

The Connection class automatically loads environment variables using Dotenv:

use Database\Connection;

// Initialize connection (loads .env automatically)
Connection::init();

// Get PDO instance
$pdo = Connection::getInstance()->getPDO();

Note: The Connection class automatically loads the .env file from the project root using vlucas/phpdotenv. Make sure your .env file contains all required database variables.

Builder Class

use Database\Builder;

$builder = new Builder('users');
$builder->select(['id', 'name'])
        ->where('status', 'active')
        ->orderBy('name')
        ->limit(10);

$sql = $builder->toSql();
$results = $builder->get();

Model Class

All models extend the base Model class:

// Static methods
Model::find($id)
Model::findOrFail($id)
Model::all()
Model::create($attributes)
Model::get($query)

// Instance methods
$model->save()
$model->delete()
$model->toArray()
$model->toJson()
$model->isDirty()

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature-name
  3. Make changes and add tests
  4. Run tests: docker-compose exec app composer test
  5. Commit changes: git commit -am 'Add feature'
  6. Push to branch: git push origin feature-name
  7. Submit a Pull Request

Development Setup

# Clone and setup
git clone <repo-url>
cd simple-php-orm
cp .env.example .env

# Start development environment
docker-compose up -d
docker-compose exec app composer install

# Run tests
docker-compose exec app composer test

Troubleshooting

Common Issues

Permission Denied

sudo chown -R $USER:$USER .
docker-compose exec app chown -R www-data:www-data /var/www/html

Database Connection Failed

  • Check .env configuration
  • Ensure MySQL container is running: docker-compose ps
  • Check logs: docker-compose logs mysql

Composer Issues

# Clear cache
docker-compose exec app composer clear-cache

# Reinstall dependencies
docker-compose exec app rm -rf vendor
docker-compose exec app composer install

Docker Issues

# Rebuild containers
docker-compose down
docker-compose build --no-cache
docker-compose up -d

License

This project is open source and available under the MIT License.

Support

  • πŸ“– Check the /public/example.php for usage examples
  • πŸ› Report issues on GitHub
  • πŸ’¬ Start discussions for questions
  • πŸ“§ Contact me for support

Changelog

v1.0.0

  • Docker development environment
  • Composer PSR-4 autoloading
  • Namespaced classes
  • Modern PHP 8.0+ support
  • Complete CRUD operations
  • Query builder with fluent interface
  • Mass assignment protection
  • JSON serialization

About

A lightweight, easy-to-use Object-Relational Mapping (ORM) library for PHP that provides an elegant Active Record implementation for working with databases. Built with modern PHP practices including Composer autoloading and Docker support.

Resources

Stars

Watchers

Forks

Packages

No packages published