Elegant ORM: Getting Started
Introduction
The Elegant ORM (Object-Relational Mapper) transforms database tables into intuitive TypeScript classes, letting you work with database records as objects rather than writing raw SQL. This object-oriented approach makes your code more maintainable, readable, and enjoyable to write.
With Elegant ORM, each database table is represented by a Model class. These models provide methods to query, insert, update, and delete records while maintaining type safety and providing a clean, expressive API.
Why Use an ORM?
Type Safety - Define your data structures once, and TypeScript ensures you're always working with the correct types.
Productivity - Write less code. Instead of crafting SQL for every operation, use intuitive methods that handle the heavy lifting.
Maintainability - Business logic stays in your application code, not scattered across SQL strings throughout your codebase.
Flexibility - When you need raw SQL power, it's always available. Elegant ORM complements rather than replaces SQL.
Generating Model Classes
To get started, let's create an Elegant model. Models typically live in the resources/database/models directory and extend the Model class. You may use the make:model Elegant command to generate a new model:
Generate corresponding type definitions for models based on database schema
Inspecting Model Structure
When working with complex models, understanding their complete structure—including all properties and connections—can be challenging through code inspection alone. The model:show command offers a quick solution by displaying a comprehensive summary of a model's attributes and relationships in an easy-to-read format:
Elegant Model Conventions
Models generated by the elegant make:model command will be placed in the resources/database/models directory. Let's examine a basic model class and discuss some of Elegant's key conventions:
Elegant follows sensible conventions to minimize configuration:
Table Names - By default, the model class name is converted to snake_case and pluralized (e.g.,
UserProfile→user_profiles)Primary Keys - Assumes an auto-incrementing column named
idTimestamps - Automatically manages
created_atandupdated_atcolumns
Table Names
By default, Elegant automatically determines which database table to use for each model through a naming convention. The framework converts the model's class name into lowercase "snake_case" and pluralizes it. For example, a User model maps to the users table, and a SocialMediaLinks model maps to the social_media_links table. When your database table doesn't follow this pattern, you can override the automatic mapping by defining a table property directly on your model:
Primary Keys
By default, Elegant expects every database table to include a primary key column called id. To use a different column as your primary key, define a protected primaryKey property on your model:
Timestamps
By default, Elegant looks for created_at and updated_at columns in your model's database table. The framework automatically populates these columns whenever you create or modify a model. To disable this automatic timestamp management, set the timestamps property on your model to false:
If you need to customize the names of the columns used to store the timestamps, you may define created_at and updated_at protected properties on your model:
Database Connections
All Elegant models use your application's default database connection unless configured otherwise. To specify which connection a model should use, define a connection property on that model:
Default Attribute Values
When you create a new model instance, its attributes start empty by default. To set initial values for specific attributes, define an attributes property on your model. Values in the attributes array must be in their raw database format—the same format used when retrieving data directly from the database:
Configuring Strictness
Elegant provides configuration options to control its behavior and strictness across different scenarios. The lazyLoading option determines whether lazy loading is enabled. This is particularly useful for development environments—you can disable lazy loading during development to catch relationship loading issues early, while keeping it enabled in production to maintain normal operation even if lazy-loaded relationships slip through. Configure this setting in your elegant.config.js file.
The strictAttributes option makes Elegant throw an exception when you attempt to populate a non-fillable attribute. Enabling this during local development helps catch errors early when you try to set attributes that haven't been added to the model's fillable array:
Retrieving Models
After creating a model and its corresponding database table, you can begin querying data. Each Elegant model functions as an advanced query builder, providing a fluent interface for interacting with its associated table. The all method fetches every record from the model's table:
Elegant Models as Query Builders
Elegant models function as comprehensive query builders, giving you access to a full suite of database query methods directly from your model classes. This design means you can chain query methods fluently to construct complex database operations without dropping down to raw SQL.
Available Query Methods
Since Elegant models inherit query builder functionality, you can leverage numerous methods for filtering, sorting, aggregating, and manipulating data. These methods work seamlessly with your model instances, allowing you to build sophisticated queries using an expressive, readable syntax.
Common Query Operations Include:
Filtering: Apply conditions to narrow down results based on column values
Sorting: Order results by one or more columns in ascending or descending order
Limiting: Restrict the number of records returned
Aggregation: Calculate sums, averages, counts, and other statistical values
Joining: Combine data from multiple related tables
Grouping: Organize results by shared attribute values
Example Usage:
All query builder methods available in Elegant can be chained together and executed on your model classes, providing a powerful and intuitive interface for database interactions. For a complete reference of available methods, consult the Query Builder documentation section.
Refreshing Models
When you have an existing Elegant model instance loaded from the database, you can update it with the latest data using the fresh and refresh methods. The fresh method fetches a new copy of the model from the database without modifying the current instance:
The refresh method updates the current model instance with fresh data from the database. Additionally, any loaded relationships are also refreshed:
Finding by Primary Key
Adding Constraints
Creating and Updating Models
Creating New Records
There are several ways to create new model instances:
Method 1: Create and save
Method 2: Create with attributes
Method 3: Mass assignment
Updating Records
Update a single model
Update using query
Update or create
Deleting Models
Delete Single Records
Delete after retrieving
Delete by primary key
Delete multiple by IDs
Delete with Constraints
Delete all inactive
Delete with conditions
Relationships
Define relationships between models to work with related data:
Working with Timestamps
Elegant automatically manages created_at and updated_at timestamps:
Disable timestamps if your table doesn't use them:
Advanced Features
Using Different Conections
Specify which database connection a model should use:
Custom Queries
Drop down to raw SQL when needed:
Eager Loading
Optimize queries by loading relationships upfront:
Best Practices
Use Type Definitions - Define all model properties with TypeScript types for better IDE support
Eager Load Relationships - Avoid N+1 query problems by using eager loading
Validate Data - Implement validation in your models before saving
Use Transactions - Wrap related operations in transactions to maintain data integrity
Next Steps
Explore the Query Builder for more complex queries
Learn about Migrations to manage your database schema
Review database configuration options