### Project Configuration and Options (CMake) Source: https://github.com/commander15/qeloquent/blob/main/CMakeLists.txt Sets up the basic project information, version, and description. It also defines build options for tests, documentation, and examples, allowing users to customize the build process. ```cmake cmake_minimum_required(VERSION 3.30) project( QEloquent VERSION 1.1.0 DESCRIPTION "Qt most flexible ORM." HOMEPAGE_URL "commander15.github.io/QEloquent" LANGUAGES CXX C ) option(QELOQUENT_BUILD_TESTS "Build tests" OFF) option(QELOQUENT_BUILD_DOC "Build documentation" ON) option(QELOQUENT_BUILD_EXAMPLES "Build examples" ON) ``` -------------------------------- ### Configure Database Connection in C++ Source: https://github.com/commander15/qeloquent/blob/main/notes/RELEASE-1.0.0.md Set up a database connection for QEloquent. This example demonstrates adding a default connection named 'default' using the QSQLITE driver and specifying the database file. ```cpp Connection::addConnection("default", "QSQLITE", "database.sqlite"); ``` -------------------------------- ### Initialize Qeloquent Query Source: https://github.com/commander15/qeloquent/blob/main/doc/query_builder.md Starts a new query from a model class using the Qeloquent Query Builder. This is the entry point for constructing SQL queries. ```cpp auto query = Product::query(); ``` -------------------------------- ### Generate and Install Deployment Script (CMake) Source: https://github.com/commander15/qeloquent/blob/main/examples/store/CMakeLists.txt Generates a deployment script for the application and installs it. This script is used to package the application for distribution, ensuring all necessary Qt plugins and resources are included. ```cmake qt_generate_deploy_app_script( TARGET Store OUTPUT_SCRIPT deploy_script NO_TRANSLATIONS NO_UNSUPPORTED_PLATFORM_ERROR ) install(SCRIPT ${deploy_script}) ``` -------------------------------- ### Build Fluent Database Queries in C++ Source: https://github.com/commander15/qeloquent/blob/main/notes/RELEASE-1.0.0.md Construct database queries using a chainable API provided by QEloquent's Query Builder. This example demonstrates filtering products by price, ordering by name, and limiting the results before fetching them. ```cpp auto query = Product::query() .where("price", ">", 100) .orderBy("name") .limit(10); auto products = Product::find(query); ``` -------------------------------- ### Manage Database Transactions (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/connections.md Demonstrates how to manage SQL transactions using the Connection class. It includes starting a transaction, performing work, and then either committing or rolling back the transaction based on the success of the operations. ```cpp Connection conn = Connection::defaultConnection(); if (conn.beginTransaction()) { bool success = doWork(); if (success) { conn.commitTransaction(); } else { conn.rollbackTransaction(); } } ``` -------------------------------- ### Install Qeloquent Library and Headers (CMake) Source: https://github.com/commander15/qeloquent/blob/main/src/CMakeLists.txt This CMake snippet defines the installation rules for the Qeloquent library. It specifies where the library archives, dynamic libraries, executables, public headers, and private headers should be installed on the target system. ```cmake install(TARGETS QEloquent EXPORT QEloquentExport ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/QEloquent PRIVATE_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/QEloquent/private ) generate_target_headers(QEloquent FOLDER QEloquent) ``` -------------------------------- ### Build QEloquent from Source (Bash) Source: https://github.com/commander15/qeloquent/blob/main/README.md Instructions for cloning the QEloquent repository, configuring the build with CMake, and installing the library. Requires Qt 6.x, CMake 3.30+, and a C++20 compliant compiler. ```bash git clone https://github.com/commander15/QEloquent.git cd QEloquent mkdir build && cd build cmake -S .. -DCMAKE_PREFIX_PATH=/path/to/Qt6 -DCMAKE_INSTALL_PREFIX=/path/to/prefix cmake --build . --target install ``` -------------------------------- ### Add Database Connection using Parameters (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/connections.md Adds a new database connection by explicitly providing connection parameters such as driver name, database name, host, and port. This offers a more granular control over connection setup. ```cpp Connection::addConnection("billing", "QPSQL", "billing_db", 5432, "user", "pass"); ``` -------------------------------- ### Performing Database Transactions in C++ Source: https://context7.com/commander15/qeloquent/llms.txt Illustrates how to manage database transactions using the QEloquent::Connection class in C++. This includes starting a transaction, performing multiple database operations, and committing or rolling back based on the success of these operations. ```cpp void performTransaction() { QEloquent::Connection conn = QEloquent::Connection::defaultConnection(); if (conn.beginTransaction()) { bool success = true; // Perform multiple operations User user; user.name = "Transaction User"; user.email = "tx@example.com"; if (!user.save()) { success = false; } Product product; product.name = "Transaction Product"; product.price = 99.99; if (!product.save()) { success = false; } // Commit or rollback based on success if (success) { conn.commitTransaction(); qDebug() << "Transaction committed successfully"; } else { conn.rollbackTransaction(); qWarning() << "Transaction rolled back due to errors"; } } } ``` -------------------------------- ### Configure and Install Qeloquent Package (CMake) Source: https://github.com/commander15/qeloquent/blob/main/src/CMakeLists.txt This CMake code configures and installs the Qeloquent package configuration files. It uses CMake's helper functions to generate the `QEloquentConfig.cmake` and `QEloquentConfigVersion.cmake` files, making Qeloquent discoverable by other CMake projects. ```cmake include(CMakePackageConfigHelpers) set(PACKAGE_DIR ${PROJECT_BINARY_DIR}/lib/cmake/QEloquent) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/QEloquentConfig.cmake.in" "${PACKAGE_DIR}/QEloquentConfig.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/QEloquent" ) write_basic_package_version_file( "${PACKAGE_DIR}/QEloquentConfigVersion.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion ) install(FILES "${PACKAGE_DIR}/QEloquentConfig.cmake" "${PACKAGE_DIR}/QEloquentConfigVersion.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/QEloquent" ) install(EXPORT QEloquentExport FILE QEloquentTargets.cmake NAMESPACE QEloquent:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/QEloquent" ) ``` -------------------------------- ### Configure and Build Doxygen Documentation with CMake Source: https://github.com/commander15/qeloquent/blob/main/doc/CMakeLists.txt This snippet finds the Doxygen executable, configures the Doxyfile using CMake's configure_file, and defines a custom target 'doc' to generate the API documentation. It also includes installation instructions for the generated documentation. ```cmake find_package(Doxygen) if(DOXYGEN_FOUND) set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) add_custom_target(doc ALL COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" SOURCES Doxyfile.in introduction.md model_definition.md usage.md VERBATIM ) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doxygen DESTINATION doc/QEloquent) else() message(STATUS "Doxygen not found, 'doc' target will not be available") endif() ``` -------------------------------- ### Advanced Model Querying with Qeloquent Query Builder Source: https://github.com/commander15/qeloquent/blob/main/README.md Illustrates how to use the Qeloquent Query builder to construct complex queries with multiple conditions, ordering, and limits. The `query()` function from `ModelHelpers` is used to start building the query. ```cpp auto query = User::query() .where("active", true) .andWhere("age", ">", 18) .orderBy("created_at", Qt::DescendingOrder) .limit(10); auto results = User::find(query); if (results) { for (const User &user : results) { qDebug() << "User: " << user.name; } } ``` -------------------------------- ### Eager Load Relationships in C++ Source: https://github.com/commander15/qeloquent/blob/main/notes/RELEASE-1.0.0.md Optimize database performance by eager-loading relationships with QEloquent's `with()` method. This prevents the N+1 query problem by fetching related data in a single query, as shown in the example loading 'products' and their 'stock' for each category. ```cpp auto query = Category::query().with("products.stock"); auto categories = Category::find(query); ``` -------------------------------- ### Conditional Subdirectory Inclusion (CMake) Source: https://github.com/commander15/qeloquent/blob/main/CMakeLists.txt Includes subdirectories for source code, tests, documentation, and examples based on the build options defined earlier. This modularizes the build process. ```cmake add_subdirectory(src) if (QELOQUENT_BUILD_TESTS) set(ENV{CTEST_OUTPUT_ON_FAILURE} ON) enable_testing() add_subdirectory(tests) endif() if (QELOQUENT_BUILD_DOC) add_subdirectory(doc) endif() if (QELOQUENT_BUILD_EXAMPLES AND Qt6Widgets_FOUND) add_subdirectory(examples/store) endif() ``` -------------------------------- ### Define Eloquent-Style Models in C++ Source: https://github.com/commander15/qeloquent/blob/main/notes/RELEASE-1.0.0.md Define data structures using Qt properties and metadata with QEloquent. This example shows a 'Product' model inheriting from QEloquent::Model and QEloquent::ModelHelpers, utilizing Q_GADGET and Q_PROPERTY for attribute definition and specifying the table name. ```cpp class Product : public QEloquent::Model, public QEloquent::ModelHelpers { Q_GADGET Q_PROPERTY(int id MEMBER id) Q_PROPERTY(QString name MEMBER name) // ... Q_CLASSINFO("table", "products") // Optional: guessed from class name public: Q_INVOKABLE QEloquent::Relation category() const { return belongsTo(); } }; ``` -------------------------------- ### Serialize Qeloquent Models to JSON in C++ Source: https://context7.com/commander15/qeloquent/llms.txt Illustrates serializing Qeloquent models to JSON format. It covers converting model data, including appended attributes but excluding hidden fields, into a QJsonObject. The example also shows how to output the JSON document and a YAML-like debug representation. ```cpp #include #include void serializeModel() { auto result = User::find(1); if (result) { User user = result.value(); // Serialize to DataMap (QList>) auto dataMap = user.fullDataMap(); // Convert to JSON (hidden fields like "password" are excluded) // Appended attributes like "emailHeader" are included QJsonObject json; for (const auto &pair : user.serialize()) { for (const auto &entry : pair) { json[entry.first] = QJsonValue::fromVariant(entry.second); } } QJsonDocument doc(json); qDebug() << doc.toJson(QJsonDocument::Indented); // Output: // { // "id": 1, // "name": "John Doe", // "email": "john@example.com", // "email_header": "John Doe " // } // Debug output produces YAML-like format qDebug() << user; } } ``` -------------------------------- ### Define QEloquent Models with Qt Meta-Object System Source: https://context7.com/commander15/qeloquent/llms.txt Defines models by inheriting from `QEloquent::Model` and `QEloquent::ModelHelpers`. Uses Qt's `Q_PROPERTY`, `Q_CLASSINFO`, and `Q_GADGET` macros for database mapping, naming conventions, field visibility, fillable properties, computed attributes, and eager loading. Includes an example of a `belongsTo` relationship. ```cpp #include #include struct User : public QEloquent::Model, public QEloquent::ModelHelpers { Q_GADGET // Database-mapped fields Q_PROPERTY(int id MEMBER id) Q_PROPERTY(QString name MEMBER name) Q_PROPERTY(QString email MEMBER email) Q_PROPERTY(QString password MEMBER password) Q_PROPERTY(int roleId MEMBER roleId) // Configuration via Q_CLASSINFO Q_CLASSINFO("table", "users") // Explicit table name (optional) Q_CLASSINFO("naming", "Laravel") // Naming convention: Laravel or OneOne Q_CLASSINFO("hidden", "password, roleId") // Hide from JSON serialization Q_CLASSINFO("fillable", "name, email, password") // Mass-assignable fields Q_CLASSINFO("append", "emailHeader") // Computed attributes Q_CLASSINFO("with", "role") // Eager-loaded relations QELOQUENT_MODEL_HELPERS(User) // Required for inherited models public: int id = 0; QString name; QString email; QString password; int roleId = 0; // Computed attribute (included in serialization via "append") Q_INVOKABLE QString emailHeader() const { return name + " <" + email + ">"; } // Relation: belongsTo Q_INVOKABLE QEloquent::Relation role() const { return belongsTo("role_id", "id"); } }; ``` -------------------------------- ### Define Model Relationships in C++ Source: https://context7.com/commander15/qeloquent/llms.txt Defines relationships between models using methods like `hasOne`, `hasMany`, `belongsTo`, and `belongsToMany`. QEloquent can automatically infer foreign keys based on naming conventions, simplifying relationship setup. ```cpp struct Category : public QEloquent::Model, public QEloquent::ModelHelpers { Q_GADGET Q_PROPERTY(int id MEMBER id) Q_PROPERTY(QString name MEMBER name) Q_PROPERTY(QString description MEMBER description) public: int id = 0; QString name; QString description; // One-to-many: Category has many Products Q_INVOKABLE QEloquent::Relation products() const { return hasMany(); // Auto-infers foreign key "category_id" } }; struct Product : public QEloquent::Model, public QEloquent::ModelHelpers { Q_GADGET Q_PROPERTY(int id MEMBER id) Q_PROPERTY(QString name MEMBER name) Q_PROPERTY(double price MEMBER price) Q_PROPERTY(int categoryId MEMBER categoryId) public: int id = 0; QString name; double price = 0.0; int categoryId = 0; // Many-to-one: Product belongs to Category Q_INVOKABLE QEloquent::Relation category() const { return belongsTo(); // Auto-infers keys } // One-to-one: Product has one Stock Q_INVOKABLE QEloquent::Relation stock() const { return hasOne("product_id", "id"); } }; ``` -------------------------------- ### Define Qeloquent Model in C++ Source: https://github.com/commander15/qeloquent/blob/main/doc/model_definition.md This C++ code snippet demonstrates the basic structure for defining a Qeloquent model. It inherits from QEloquent::Model and QEloquent::ModelHelpers, uses Q_PROPERTY for database fields, and Q_CLASSINFO for configuration like table names, naming conventions, hidden fields, fillable properties, appended attributes, and eager loading. It also includes examples of defining one-to-one/many-to-one and many-to-many relationships. ```cpp #include #include struct User : public QEloquent::Model, public QEloquent::ModelHelpers { Q_GADGET // Core fields — mapped directly to database columns Q_PROPERTY(int id MEMBER id) Q_PROPERTY(QString name MEMBER name) Q_PROPERTY(QString email MEMBER email) Q_PROPERTY(QString password MEMBER password) // Optional: Explicit table name. // By default, QEloquent converts the class name to to an appropriate table name // according to the naming convention set. // For Laravel naming convention, we can have: "User" → "users". Q_CLASSINFO("table", "users") // Optional: Naming convention. // "Laravel" (default): class name → snake_case + pluralized for table name, // property name → snake_case for column name. // "OneOne" alternative: property name = column name exactly, // table name = class name pluralized. Q_CLASSINFO("naming", "Laravel") // Optional: Hide fields from serialization (e.g., JSON output). // Use property names here — the corresponding database fields will be omitted // from serialized output. // If the properties are not regular (Q_PROPERTY based), they are considered as // dynamic properties so don't need to worry if they are used for relation resolution // They don't appear during serialization but they are still there and accessible // using property() method. Q_CLASSINFO("hidden", "password, roleId") // Optional: Mass-assignable (fillable) properties. // By default, all writable Q_PROPERTY and dynamic properties are fillable. // Restricting this protects against mass-assignment vulnerabilities. // Note: only regular writable and dynamic properties supported Q_CLASSINFO("fillable", "name, email, password") // Optional: Computed/appended attributes. // These are not stored in the database but are included in serialization and debug output. // The key name in output will follow the naming convention (e.g., snake_case) if no // override had been provided (see note below). // Requires a parameterless Q_INVOKABLE accessor with the same name. Q_CLASSINFO("append", "emailHeader") // Optional: Eager loading. // Relations listed here are automatically loaded whenever the model is retrieved. // Requires a parameterless Q_INVOKABLE relation method with the same name. Q_CLASSINFO("with", "role") // Required when inheriting from a model that already includes ModelHelpers. // Resolves potential static method ambiguity. QELOQUENT_MODEL_HELPERS(User) public: // Database-mapped fields int id = 0; QString name; QString email; QString password; // Appended (computed) attribute Q_INVOKABLE QString emailHeader() const { // This value will appear in JSON/debug output thanks to "append" return name + " <" + email + ">"; } // One-to-one / many-to-one relation Q_INVOKABLE QEloquent::Relation role() const { // Parameters are optional — QEloquent can often infer them automatically return belongsTo("role_id", "id"); } // Many-to-many relation Q_INVOKABLE QEloquent::Relation groups() const { // Pivot table and key names — also often auto-deducible return belongsToMany("UserGroupMembers", "user_id", "group_id"); } }; ``` -------------------------------- ### Set up Database Connection (C++) Source: https://github.com/commander15/qeloquent/blob/main/README.md Demonstrates how to establish a database connection using QEloquent's Connection class. This code snippet initializes a connection named 'DB' using the QSQLITE driver and an in-memory SQLite database. It includes error handling for connection failures. ```cpp #include void setup() { // First added connection is considered as the default one ! auto conn = QEloquent::Connection::addConnection("DB", "QSQLITE", ":memory:"); if (!conn.open()) { qCritical() << "Failed to open database:" << conn.lastError().text(); return; } } ``` -------------------------------- ### Fetch and Use Google Test (CMake) Source: https://github.com/commander15/qeloquent/blob/main/tests/CMakeLists.txt Fetches the Google Test framework from GitHub using FetchContent. It declares the repository and tag, then makes it available for use in the project. This is a standard way to manage external dependencies in CMake projects. ```cmake set(BUILD_GMOCK OFF) include(FetchContent) FetchContent_Declare(GTest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.14.0 ) FetchContent_MakeAvailable(GTest) ``` -------------------------------- ### Create Model Instance with Qeloquent Source: https://github.com/commander15/qeloquent/blob/main/README.md Demonstrates how to create a new model instance and persist it to the database using the `create` method. It handles potential success or failure of the operation. ```cpp QJsonObject data; data["name"] = "John Doe"; auto result = User::create(data); if (result) { User user = result.value(); qDebug() << "Created user with ID:" << user.id; } else { qWarning() << "Create failed:" << result.error().text(); } ``` -------------------------------- ### Database Migrations Schema Definition and Execution in C++ Source: https://context7.com/commander15/qeloquent/llms.txt Shows how to define and run database migrations using QEloquent::Migration and QEloquent::Migrator in C++. It includes creating tables with a fluent schema builder and executing migrations with a progress callback. Rollback functionality is also demonstrated. ```cpp #include #include QEloquent::Result setupSchema() { QEloquent::Migration::enableAutoRegistration(); // Create users table QEloquent::Migration::createTable("users", [](QEloquent::TableBlueprint &table) { table.id(); // Auto-incrementing primary key table.string("name", 30); // VARCHAR(30) table.string("email", 60).unique(); // Unique constraint table.string("password", 64); table.foreignId("role_id").references("id").on("user_roles"); table.timestamps(); // created_at, updated_at }); // Create products table QEloquent::Migration::createTable("products", [](QEloquent::TableBlueprint &table) { table.id(); table.string("name", 30); table.string("description").nullable(); // Nullable column table.decimal("price").min(0.0); // Decimal with minimum value table.string("barcode", 20).nullable(); table.foreignId("category_id").on("categories").references("id"); table.timestamps(); }); // Create stocks table QEloquent::Migration::createTable("stocks", [](QEloquent::TableBlueprint &table) { table.id(); table.unsignedInteger("quantity").min(0); table.foreignId("product_id").on("products").references("id"); table.timestamps("created_at", "updated_at"); }); QEloquent::Migration::disableAutoRegistration(); // Run migrations with progress callback return QEloquent::Migrator::migrate([](const QEloquent::Migration *migration) { qDebug() << "Running migration:" << migration->name(); }); } void rollbackSchema() { QEloquent::Migrator::rollback([](const QEloquent::Migration *migration) { qDebug() << "Reverting migration:" << migration->name(); }, 10); // Rollback last 10 migrations } ``` -------------------------------- ### Retrieve Last Error from Qeloquent Instance Method in C++ Source: https://github.com/commander15/qeloquent/blob/main/doc/error_handling.md Illustrates how to get the last error from a Qeloquent model instance after an operation like save() fails. This provides specific details about the failure. ```cpp if (!user.save()) { qWarning() << "Save failed:" << user.lastError().text(); } ``` -------------------------------- ### Paginate Qeloquent Queries Source: https://github.com/commander15/qeloquent/blob/main/doc/query_builder.md Explains how to implement pagination for query results using limit and offset. Includes a helper method for specifying page number and items per page. ```cpp query.limit(10).offset(20); query.page(2, 50); // Page 2, 50 per page (Offset 50, Limit 50) ``` -------------------------------- ### Create Records in QEloquent Source: https://context7.com/commander15/qeloquent/llms.txt Demonstrates two methods for creating new records: using the static `create()` method with a `QJsonObject`, and by manually instantiating a model object and calling its `save()` method. Includes error handling for failed operations. ```cpp #include void createUser() { // Method 1: Using static create() with QJsonObject QJsonObject data; data["name"] = "John Doe"; data["email"] = "john@example.com"; data["password"] = "hashed_password_here"; data["roleId"] = 1; auto result = User::create(data); if (result) { User user = result.value(); qDebug() << "Created user with ID:" << user.id; // Output: Created user with ID: 1 } else { qWarning() << "Create failed:" << result.error().text(); } // Method 2: Manual instantiation and save User newUser; newUser.name = "Jane Smith"; newUser.email = "jane@example.com"; newUser.password = "another_hashed_password"; newUser.roleId = 2; if (newUser.save()) { qDebug() << "Saved user with ID:" << newUser.id; } else { qWarning() << "Save failed:" << newUser.lastError().text(); } } ``` -------------------------------- ### Create Record with Qeloquent Source: https://github.com/commander15/qeloquent/blob/main/doc/usage.md Persists new data to the database using the static `create()` method. It takes a QJsonObject as input and returns a QVariant containing the created Product object on success. ```cpp QJsonObject data; data["name"] = "Smartphone"; data["price"] = 699.99; auto result = Product::create(data); if (result) { Product p = result.value(); qDebug() << "Created product with ID:" << p.id; } ``` -------------------------------- ### Add Database Connection using URL (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/connections.md Adds a new database connection using a QUrl object. The first connection added is typically set as the default. This method is useful for specifying connection details like the database driver and path in a single URL string. ```cpp auto conn = Connection::addConnection("default", QUrl("sqlite:///path/to/db.sqlite")); ``` -------------------------------- ### Implicit Conversion of Relations to Models with Qeloquent Source: https://github.com/commander15/qeloquent/blob/main/README.md Explains and demonstrates how a relation can be implicitly converted to a model instance, such as calling `.first()` on a relation. If no related model exists, a default-constructed model is returned. ```cpp Stock stock = product.stock(); // Implicitly calls .first() if (stock.exists()) { qDebug() << "Stock level:" << stock.quantity; } ``` -------------------------------- ### Using Relationships with Transparent Loading in C++ Source: https://context7.com/commander15/qeloquent/llms.txt Demonstrates how to access related models using transparent lazy loading in C++. Relations are automatically fetched from the database on first access, and eager loading can be used to prevent N+1 query issues. ```cpp void useRelationships() { // One-to-many: Iterate over related products auto catResult = Category::find(1); if (catResult) { Category category = catResult.value(); // Transparent loading: query executes on first iteration for (const Product &product : category.products()) { qDebug() << "Product:" << product.name << "- $" << product.price; } } // Many-to-one: Pointer-like access with -> auto prodResult = Product::find(1); if (prodResult) { Product product = prodResult.value(); // Access related category directly qDebug() << "Category:" << product.category()->name; // Output: Category: "Electronics" } // Implicit conversion to model auto result = Product::find(1); if (result) { Product product = result.value(); Stock stock = product.stock(); // Implicitly calls .first() if (stock.exists()) { qDebug() << "Stock quantity:" << stock.quantity; } } // Eager loading to avoid N+1 queries auto users = User::find(User::query().limit(10)); if (users) { for (auto &user : users.value()) { user.load("role"); // Batch load relations } } } ``` -------------------------------- ### Configure Database Connections with QEloquent Source: https://context7.com/commander15/qeloquent/llms.txt Sets up database connections using the `Connection` class, which wraps `QSqlDatabase`. Supports multiple database types (SQLite, PostgreSQL) and connection methods (parameters, URL). The first connection added becomes the default. ```cpp #include void setupDatabase() { // Add SQLite connection (first connection is default) auto conn = QEloquent::Connection::addConnection("DB", "QSQLITE", ":memory:"); if (!conn.open()) { qCritical() << "Failed to open database:" << conn.lastError().text(); return; } // Add PostgreSQL connection with full parameters QEloquent::Connection::addConnection("billing", "QPSQL", "billing_db", 5432, "user", "pass"); // Add connection using URL auto logConn = QEloquent::Connection::addConnection("logs", QUrl("sqlite:///path/to/logs.sqlite")); // Retrieve and use a specific connection QEloquent::Connection billing = QEloquent::Connection::connection("billing"); if (billing.open()) { qDebug() << "Connected to billing database"; } } ``` -------------------------------- ### External Dependency Fetching (CMake) Source: https://github.com/commander15/qeloquent/blob/main/CMakeLists.txt Fetches the 'expected' library from GitHub using FetchContent. This ensures the dependency is available for the project. ```cmake include(FetchContent) FetchContent_Declare( Expected GIT_REPOSITORY https://github.com/TartanLlama/expected.git GIT_TAG v1.3.1 ) FetchContent_MakeAvailable(Expected) ``` -------------------------------- ### Assign Model-Specific Database Connections in C++ Source: https://context7.com/commander15/qeloquent/llms.txt Shows how to configure Qeloquent models to use specific database connections beyond the default. By using Q_CLASSINFO("connection", "..."), models can be directed to different databases, as demonstrated with 'User' using the default and 'LogEntry' using a 'logging' connection. ```cpp struct LogEntry : public QEloquent::Model, public QEloquent::ModelHelpers { Q_GADGET Q_PROPERTY(int id MEMBER id) Q_PROPERTY(QString message MEMBER message) Q_PROPERTY(QDateTime timestamp MEMBER timestamp) // Use "logging" connection instead of default Q_CLASSINFO("connection", "logging") public: int id = 0; QString message; QDateTime timestamp; }; void useMultipleConnections() { // Setup connections QEloquent::Connection::addConnection("default", "QSQLITE", "main.db"); QEloquent::Connection::addConnection("logging", "QSQLITE", "logs.db"); // User uses default connection auto user = User::find(1); // LogEntry automatically uses "logging" connection LogEntry entry; entry.message = "User logged in"; entry.timestamp = QDateTime::currentDateTime(); entry.save(); // Saved to logs.db } ``` -------------------------------- ### Order and Group Qeloquent Queries Source: https://github.com/commander15/qeloquent/blob/main/doc/query_builder.md Shows how to specify ordering and grouping for query results. Supports ordering by a column in ascending or descending order, and grouping by a specified column. ```cpp query.orderBy("created_at", Qt::DescendingOrder); query.groupBy("category_id"); ``` -------------------------------- ### Read Model Instances with Qeloquent Source: https://github.com/commander15/qeloquent/blob/main/README.md Shows two methods for retrieving model instances: finding by primary key and using the query builder to find models based on specific criteria. Both methods return a `Result` object that can contain the model(s) or an error. ```cpp // Find by primary key (returns Result) auto result = User::find(1); if (result) { User user = result.value(); qDebug() << "Found:" << user.name; } else { qWarning() << "User not found or DB error:" << result.error().text(); } // Find using Query Builder (returns Result, Error>) auto users = User::find(User::query().where("name", "John Doe")); if (!users) { qWarning() << "Query failed:" << users.error().text(); } ``` -------------------------------- ### Packaging Configuration (CMake) Source: https://github.com/commander15/qeloquent/blob/main/CMakeLists.txt Sets up packaging options for the project, including package name, vendor, directory, and generators. It supports ZIP and TGZ generators based on the operating system. ```cmake # Packaging set(CPACK_PACKAGE_NAME QEloquent) set(CPACK_PACKAGE_VENDOR Amadou Benjamain) set(CPACK_PACKAGE_DIRECTORY packages) set(CPACK_GENERATOR ZIP) if (LINUX) list(APPEND CPACK_GENERATOR TGZ) endif() include(CPack) ``` -------------------------------- ### Access Database Connection by Name (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/connections.md Retrieves a configured database connection by its registered name. The connection is then opened and can be used for database operations. Error handling for connection opening is recommended. ```cpp Connection conn = Connection::connection("billing"); if (conn.open()) { // ... } ``` -------------------------------- ### Update and Delete Model Instances with Qeloquent Source: https://github.com/commander15/qeloquent/blob/main/README.md Illustrates how to update an existing model's properties and then save the changes, or how to delete the model from the database. Both operations are performed on a retrieved model instance and include error handling. ```cpp auto result = User::find(1); if (result) { User user = result.value(); user.name = "Jane Doe"; if (!user.save()) { qWarning() << "Update failed:" << user.lastError().text(); } if (!user.deleteData()) { qWarning() << "Delete failed:" << user.lastError().text(); } } ``` -------------------------------- ### Eager Load Relations in Qeloquent Source: https://github.com/commander15/qeloquent/blob/main/doc/query_builder.md Demonstrates how to use eager loading to fetch related models automatically, preventing N+1 query problems. This improves performance when accessing related data. ```cpp auto result = Product::find(Product::query().with("category")); ``` -------------------------------- ### Define Qt Executable and Link Libraries (CMake) Source: https://github.com/commander15/qeloquent/blob/main/examples/store/CMakeLists.txt Defines the main executable for the Qt application, lists its source files, and links it against Qt6::Widgets and QEloquent. This is a standard way to build Qt applications with CMake. ```cmake set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) qt_add_executable(Store main.cpp models/user.h models/user.cpp models/product.h models/product.cpp models/sale.h models/sale.cpp ui/mainwindow.h ui/mainwindow.cpp ui/dashboardview.h ui/dashboardview.cpp ui/logindialog.h ui/logindialog.cpp ui/session.h models/model.h models/model.cpp common.h migration.cpp seeding.cpp ) target_link_libraries(Store PRIVATE Qt6::Widgets QEloquent) install(TARGETS Store RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) ``` -------------------------------- ### Output Directory Configuration (CMake) Source: https://github.com/commander15/qeloquent/blob/main/CMakeLists.txt Configures the output directories for runtime executables, static libraries, and shared libraries. This helps in organizing the build artifacts. ```cmake set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) ``` -------------------------------- ### Query Records with Query Builder in C++ Source: https://context7.com/commander15/qeloquent/llms.txt Constructs complex SQL queries using a fluent Query Builder interface without writing raw SQL. It supports filtering, ordering, grouping, and pagination. The builder can also be used for eager loading to prevent N+1 query problems. ```cpp void queryUsers() { // Build a complex query auto query = User::query() .where("active", true) .andWhere("age", ">", 18) .orWhere("role_id", 1) .orderBy("created_at", Qt::DescendingOrder) .limit(10) .offset(20); auto results = User::find(query); if (results) { QList users = results.value(); for (const User &user : users) { qDebug() << "User:" << user.name; } } // Pagination helper auto pageQuery = User::query() .where("active", true) .page(2, 50); // Page 2, 50 per page (offset 50, limit 50) // Grouping auto groupQuery = User::query() .groupBy("role_id") .orderBy("name", Qt::AscendingOrder); // Eager loading to prevent N+1 queries auto eagerQuery = User::query().with("role"); auto usersWithRoles = User::find(eagerQuery); } ``` -------------------------------- ### Eager Load Qeloquent Relations (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/relations.md Explains how to prevent N+1 query problems by eagerly loading relations using the `load()` method. This fetches all related data in a single query, improving performance for bulk operations. ```cpp auto users = User::find(User::query().limit(10)); for (auto &user : users.value()) { user.load("posts"); // Eagerly loads all related posts in one query } ``` -------------------------------- ### Define QEloquentTest Executable (CMake) Source: https://github.com/commander15/qeloquent/blob/main/tests/CMakeLists.txt Defines the main test executable 'QEloquentTest' using qt_add_executable. It lists all the source files required for the executable, including headers and implementation files for various models and core functionalities. Conditional sources can be added using target_sources. ```cmake qt_add_executable(QEloquentTest main.cpp core/mytest.h core/mytest.cpp models/invalidmodels.h models/invalidmodels.cpp models/simplemodels.h models/simplemodels.cpp models/complexmodels.h models/complexmodels.cpp metadata.h metadata.cpp querygenerator.h querygenerator.cpp serialization.h serialization.cpp simplemodel.h simplemodel.cpp complexmodel.h complexmodel.cpp ) if (TRUE) target_sources(QEloquentTest PRIVATE schema.h schema.cpp migration.h migration.cpp ) endif() target_include_directories(QEloquentTest PRIVATE . core models) target_link_libraries(QEloquentTest PRIVATE gtest QEloquent) target_compile_definitions(QEloquentTest PRIVATE TEST_DATA_DIR="${TEST_DATA}" TEST_DB_NAME="${TEST_DB}" ) add_test(NAME QEloquentTest COMMAND QEloquentTest CONFIGURATIONS) ``` -------------------------------- ### Read Records with Qeloquent Source: https://github.com/commander15/qeloquent/blob/main/doc/usage.md Retrieves records from the database. Supports finding by primary key using `find()` or using the Query Builder for complex filtering and sorting. ```cpp auto result = Product::find(1); if (result) { Product p = result.value(); qDebug() << "Product Name:" << p.name; } ``` ```cpp auto query = Product::query() .where("price", ">", 500) .orderBy("name", Qt::AscendingOrder); auto result = Product::find(query); if (result) { QList products = result.value(); // ... } ``` -------------------------------- ### Filter Qeloquent Queries (WHERE clauses) Source: https://github.com/commander15/qeloquent/blob/main/doc/query_builder.md Demonstrates how to apply WHERE clauses to filter query results. Supports simple equality, custom operators like '>=', and logical AND/OR combinations. ```cpp query.where("category_id", 5); query.where("price", ">=", 100); query.where("active", true) .orWhere("price", "<", 10); ``` -------------------------------- ### Custom Naming Convention Implementation (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/utilities.md Shows how to set a custom naming convention for Qeloquent by subclassing QEloquent::NamingConvention and setting it as the default. This is useful for integrating with legacy databases that do not follow standard conventions. ```cpp // Change global convention NamingConvention::setDefault(new MyCustomConvention()); ``` -------------------------------- ### CI/CD Workflow Configuration (CMake) Source: https://github.com/commander15/qeloquent/blob/main/CMakeLists.txt Configures arguments for the CI/CD workflow, including enabling tests and shared libraries. It also reads release notes to generate a CI/CD configuration file. ```cmake # CI/CD workflow set(CMAKE_CONFIG_ARGS -DQELOQUENT_BUILD_TESTS=ON -DBUILD_SHARED_LIBS=ON ) string(JOIN " " CMAKE_CONFIG_ARGS ${CMAKE_CONFIG_ARGS}) set(QT_VERSION 6.5.0) file(READ notes/RELEASE-${PROJECT_VERSION}.md MAIL_TEXT) string(JOIN "\n\n" MAIL_TEXT ${MAIL_TEXT}) string(REPLACE "\"" "\\\"" MAIL_TEXT ${MAIL_TEXT}) string(REPLACE "\n" "\\n" MAIL_TEXT ${MAIL_TEXT}) configure_file(.github/workflows/ci-cd.yml.in ${CMAKE_CURRENT_SOURCE_DIR}/.github/workflows/ci-cd.yml @ONLY) ``` -------------------------------- ### Implicit Conversion of Qeloquent Relations (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/relations.md Demonstrates implicit conversion of a relation to a model variable. Assigning a relation directly to a model variable retrieves the first related record. ```cpp Category cat = product.category(); ``` -------------------------------- ### Configure Qeloquent Library Build (CMake) Source: https://github.com/commander15/qeloquent/blob/main/src/CMakeLists.txt This snippet sets up the Qeloquent library build using CMake. It enables shared library building, adds the QEloquent library, and includes subdirectories for different modules. It also sets target properties, compile definitions, and links necessary libraries. ```cmake set(BUILD_SHARED_LIBS 1) qt_add_library(QEloquent) add_subdirectory(core) add_subdirectory(drivers) add_subdirectory(serialization) add_subdirectory(utils) add_subdirectory(query) add_subdirectory(meta) add_subdirectory(orm) add_subdirectory(migration) set_target_properties(QEloquent PROPERTIES VERSION ${PROJECT_VERSION} ) target_compile_definitions(QEloquent PUBLIC QELOQUENT_LIB QELOQUENT_$ PRIVATE QELOQUENT_BUILD ) target_link_libraries(QEloquent PUBLIC Qt::Sql expected) target_include_directories(QEloquent PUBLIC $ ) ``` -------------------------------- ### C++ Standard and Qt6 Integration (CMake) Source: https://github.com/commander15/qeloquent/blob/main/CMakeLists.txt Sets the C++ standard to C++20 and enables required modules for Qt6. It also finds optional Qt6 modules based on build configurations. ```cmake # C++ 20 set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Qt specifics set(CMAKE_AUTOMOC ON) # Finding Qt set(REQUIRED_MODULES Core Sql) if (QELOQUENT_BUILD_EXAMPLES) list(APPEND OPTIONAL_MODULES Widgets) endif() find_package(Qt6 REQUIRED COMPONENTS ${REQUIRED_MODULES} OPTIONAL_COMPONENTS ${OPTIONAL_MODULES}) ``` -------------------------------- ### Define Qeloquent Model with Properties and Relations (C++) Source: https://github.com/commander15/qeloquent/blob/main/README.md This C++ code defines a 'User' model inheriting from QEloquent::Model and QEloquent::ModelHelpers. It showcases how to map database columns using Q_PROPERTY, configure table names and naming conventions with Q_CLASSINFO, define hidden and fillable fields, add computed attributes (emailHeader), and set up relationships (role, groups) using Q_INVOKABLE methods. ```cpp #include #include struct User : public QEloquent::Model, public QEloquent::ModelHelpers { Q_GADGET // Core fields — mapped directly to database columns Q_PROPERTY(int id MEMBER id) Q_PROPERTY(QString name MEMBER name) Q_PROPERTY(QString email MEMBER email) Q_PROPERTY(QString password MEMBER password) // Optional: Explicit table name. // By default, QEloquent converts the class name to to an appropriate table name // according to the naming convention set. // For Laravel naming convention, we can have: "User" → "users". Q_CLASSINFO("table", "users") // Optional: Naming convention. // "Laravel" (default): class name → snake_case + pluralized for table name, // property name → snake_case for column name. // "OneOne" alternative: property name = column name exactly, // table name = class name pluralized. Q_CLASSINFO("naming", "Laravel") // Optional: Hide fields from serialization (e.g., JSON output). // Use property names here — the corresponding database fields will be omitted // from serialized output. // If the properties are not regular (Q_PROPERTY based), they are considered as // dynamic properties so don't need to worry if they are used for relation resolution // They don't appear during serialization but they are still there and accessible // using property() method. Q_CLASSINFO("hidden", "password, roleId") // Optional: Mass-assignable (fillable) properties. // By default, all writable Q_PROPERTY and dynamic properties are fillable. // Restricting this protects against mass-assignment vulnerabilities. // Note: only regular writable and dynamic properties supported Q_CLASSINFO("fillable", "name, email, password") // Optional: Computed/appended attributes. // These are not stored in the database but are included in serialization and debug output. // The key name in output will follow the naming convention (e.g., snake_case) if no // override had been provided (see note below). // Requires a parameterless Q_INVOKABLE accessor with the same name. Q_CLASSINFO("append", "emailHeader") // Optional: Eager loading. // Relations listed here are automatically loaded whenever the model is retrieved. // Requires a parameterless Q_INVOKABLE relation method with the same name. Q_CLASSINFO("with", "role") // Required when inheriting from a model that already includes ModelHelpers. // Resolves potential static method ambiguity. QELOQUENT_MODEL_HELPERS(User) public: // Database-mapped fields int id = 0; QString name; QString email; QString password; // Appended (computed) attribute Q_INVOKABLE QString emailHeader() const { // This value will appear in JSON/debug output thanks to "append" return name + " <" + email + ">"; } // One-to-one / many-to-one relation Q_INVOKABLE QEloquent::Relation role() const { // Parameters are optional — QEloquent can often infer them automatically return belongsTo("role_id", "id"); } // Many-to-many relation Q_INVOKABLE QEloquent::Relation groups() const { // Pivot table and key names — also often auto-deducible return belongsToMany("UserGroupMembers", "user_id", "group_id"); } }; ``` -------------------------------- ### Assign Connection to Model using Q_CLASSINFO (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/connections.md Specifies a database connection for a Qeloquent model using the Q_CLASSINFO meta-information. This allows different models to use different database connections, overriding the default. ```cpp struct LogEntry : public Model, public ModelHelpers { Q_GADGET Q_CLASSINFO("connection", "logging") // ... }; ``` -------------------------------- ### Iterate Qeloquent hasMany Relations (C++) Source: https://github.com/commander15/qeloquent/blob/main/doc/relations.md Shows how to iterate over a 'hasMany' relation using a range-based for loop, treating the relation similar to a standard C++ container. This allows easy access to each related model. ```cpp for (const Product &product : category.products()) { qDebug() << "Product:" << product.name; } ```