Sukarix is an open-source modern PHP framework built to empower developers by facilitating rapid development of web and CLI applications with a focus on simplicity and efficiency. Born out of the need for a streamlined, performance-oriented framework, Sukarix builds on top of the Fat-Free Framework to offer a solid foundation that is both lightweight and feature-rich.

Introduction

Philosophy

Sukarix Framework embraces a philosophy built on principles designed to enhance your development process and deliver robust, scalable applications. Here’s what defines our approach:

  1. Lean yet Robust

    • Powered with F3 (Fat-Free Framework): While F3 provides a lightweight core, Sukarix builds on this foundation, adding just the right amount of structure and modern features to deliver a robust, feature-rich experience without overwhelming complexity.
  2. Proven Expertise

    • Real world experience: Sukarix has been rigorously tested in production environments from 2016 to 2024, covering a wide range of applications including CLI tools, web apps, React applications, APIs, middleware, and reverse proxy apps. This extensive testing under diverse conditions demonstrates the framework's reliability and versatility, ensuring its readiness for public release in 2024.
  3. Stability Over PHP Versions

    • Minimalistic upgrades: Sukarix is designed to ensure stability across different PHP versions with minimal changes required. The framework is built in such a way that upgrading your PHP version typically requires no adjustments to the framework itself, simplifying maintenance and ensuring long-term compatibility.
  4. Rich in features

    • Best-in-Class Libraries: Sukarix incorporates the best PHP libraries available from the open-source community, offering enterprise-level features that meet the demands of complex business applications.
  5. Efficiency first

    • Simplicity and Performance: When multiple approaches exist for a feature, we prioritise using the Fat-Free Framework's methods for their proven efficiency. Features are designed and continually refined to ensure the most performant outcomes while maintaining simplicity.
  6. Flexibility in approach

    • Multiple ways to succeed: While Sukarix standardises the use of the Fat-Free Framework (F3), it remains flexible, allowing developers to utilize F3’s core features, its plugins, and a range of open-source libraries to craft alternative solutions. This approach provides developers the freedom to choose or create the method that best fits the specific requirements of their projects.
  7. Smart defaults

    • Convention Over Configuration: Sukarix is built on the principle of "It just works!" By promoting conventions over configurations, the framework provides smart defaults that streamline development tasks, enabling developers to focus more on innovation and less on setup.
  8. Testability

    • Comprehensive Testing: Sukarix is equipped with built-in tools for both CLI and browser-based unit testing, ensuring the reliability and performance of applications through thorough testing. While the framework does not depend on PHPUnit, developers have the flexibility to integrate it or any other testing frameworks into their projects as needed.

Features

  • Intuitive Routing System: Define your routes intuitively, ensuring that your application logic is separated from the routing layer and stay human-readable.
  • Powerful Templating Engine: Comes with a powerful templating engine that facilitates creating dynamic content in a clean and manageable way.
  • Built-in Caching Solutions: Reduce load times and enhance application performance with advanced caching techniques.
  • ORM Layer: Simplify database interactions with a robust ORM that supports a variety of database systems.

Getting Started

Starting with Sukarix is straightforward. Our documentation is designed to guide you through setting up your development environment, creating your first project, and exploring Sukarix’s capabilities. Whether you’re building a small website or a complex application, Sukarix provides all the tools you need to succeed.

Contributing

Sukarix is an open-source project and thrives on your contributions. Whether it's fixing bugs, adding features, or improving documentation, your help is always welcome. Join our community and help shape the future of Sukarix!

The Sukarix Framework

What is Sukarix?

Sukarix is an open-source PHP framework built on top of the Fat-Free Framework (F3) designed to create enterprise-grade web and server/CLI applications. The name "Sukarix" is derived from the Arabic word "سُكَّر" (sukkar), which means sugar, symbolizing the framework's goal to add sweetness and efficiency to the robust and lightweight Fat-Free Framework.

Purpose of Sukarix

The primary purpose of Sukarix is to provide developers with a powerful and efficient framework for building enterprise-level PHP applications. Whether you are developing web applications or server-side/command-line interface ( CLI) applications, Sukarix aims to streamline the development process by leveraging the strengths of Fat-Free Framework and enhancing it with additional features and tools for modern development needs. Sukarix seeks to combine the best available PHP libraries to build the most robust and usable PHP framework.

Why Choose Sukarix?

Stability Across PHP Upgrades

One of the key strengths of Sukarix, inherited from Fat-Free Framework, is its stability across PHP upgrades. The framework is designed to be robust and reliable, ensuring that your code remains functional and intact even as PHP evolves. This minimizes the need for extensive refactoring and reduces the risk of breaking changes during upgrades.

Robustness

Sukarix offers a robust foundation for building applications. It is designed to handle various use cases and edge scenarios gracefully, ensuring that your application remains stable and secure under different conditions. This robustness comes from years of development and real-world use, making it a trustworthy choice for enterprise applications.

Resource Efficiency

Sukarix is built to be resource-efficient. It has a minimal footprint and is optimized for performance, ensuring that it consumes fewer resources compared to heavier frameworks. This efficiency translates to faster response times and lower operational costs, making it ideal for high-performance applications.

Usability and Practicality

The Fat-Free Framework, which forms the backbone of Sukarix, boasts a well-established history of stability and performance. Over the years, it has been employed in numerous projects, showcasing its reliability and versatility. Sukarix capitalizes on this robust foundation, enhancing it with additional features to meet modern development needs.

Proven Track Record

Fat-Free Framework, the foundation of Sukarix, has a proven track record of stability and performance. It has been used in numerous projects over the years, demonstrating its reliability and versatility. Sukarix builds on this solid foundation, offering additional features and enhancements that cater to modern development needs.

Features

Introduction

Sukarix builds upon the robust and lightweight foundation of the Fat-Free Framework (F3), a micro-framework known for its efficiency and simplicity. We have retained the best features of F3 where it excels, ensuring a solid, stable, and high-performance core. At the same time, we have integrated or replaced certain components with more powerful and feature-rich libraries to make Sukarix enterprise-ready. These enhancements provide additional functionality, improve scalability, and offer a more comprehensive development experience for building complex, modern PHP applications.

Feature List

Feature NameF3 NativeSukarix Replacement (Library)
Fast and clean template engineYes-
Unit testing toolkit (Web UI & CLI)YesPHPUnit Code Coverage
Database-managed sessionsYes-
Markdown-to-HTML converterYes-
Atom/RSS feed readerYes-
Image processorYes-
Geodata handlerYes-
On-the-fly Javascript/CSS compressorYesMatthias Mullie Minify
OpenID (consumer)Yes-
Custom loggerYesMonolog
Basket/Shopping cartYes-
Pingback server/consumerYes-
Unicode-aware string functionsYes-
SMTP over SSL/TLSYesF3 Mailer
Tools for communicating with other serversYes-
Data ValidationYesSukarix extends F3
ORM-F3 Cortex
ACL-F3 Access
Multi-language-F3 Multilang
Event Dispatching-F3 Events
Messages to chat platforms-Guanguans Notify
Database Migrations-Phinx
Debugging & Global Event Catching-Tracy
Cron job scheduler-peppeocchi/php-cron-scheduler
Dependency Injection-Sukarix
Inversion of Control-Sukarix
Bash tool-Sukarix (coming...)

Description of Features

  • Fast and clean template engine: Provides a lightweight and efficient templating system that allows for easy creation of dynamic web pages.
  • Unit testing toolkit (Web UI & CLI): Integrated tools for unit testing both web interfaces and command-line interfaces, ensuring comprehensive code coverage and reliability.
  • Database-managed sessions: Manages user sessions through the database, enhancing security and scalability.
  • Markdown-to-HTML converter: Converts Markdown syntax into HTML, facilitating easy content creation and management.
  • Atom/RSS feed reader: Parses and reads Atom and RSS feeds, allowing for integration with external content sources.
  • Image processor: Handles image manipulation tasks such as resizing, cropping, and format conversion.
  • Geodata handler: Manages geographical data, enabling features such as location-based services and mapping.
  • On-the-fly Javascript/CSS compressor: Minifies JavaScript and CSS files on the fly to improve page load times and performance.
  • OpenID (consumer): Supports OpenID authentication, allowing users to log in using their existing OpenID accounts.
  • Custom logger: Enhanced logging capabilities using Monolog, providing flexible and powerful logging options.
  • Basket/Shopping cart: Manages e-commerce functionalities such as shopping carts and order processing.
  • Pingback server/consumer: Implements pingback functionality for communication between blogs and websites.
  • Unicode-aware string functions: Handles string operations with full Unicode support, ensuring compatibility with multiple languages and character sets.
  • SMTP over SSL/TLS: Securely sends emails using SMTP with SSL/TLS encryption, enhancing email security.
  • Tools for communicating with other servers: Provides utilities for making HTTP requests and interacting with external APIs.
  • Data Validation: Sukarix extends F3 to validate input data, ensuring it meets specified rules and constraints before processing.
  • ORM: Uses F3 Cortex for object-relational mapping, simplifying database interactions.
  • ACL: Manages access control using F3 Access, enforcing permissions and roles.
  • Multi-language: Supports multiple languages using F3 Multilang, allowing for easy localisation of content adn routes.
  • Event Dispatching: Handles event management using F3 Events, allowing for flexible and decoupled event-driven architecture.
  • Messages to chat platforms: Sends notifications to chat platforms like Zulip and Slack using Guanguans Notify.
  • Database Migrations: Manages database schema changes using Phinx, ensuring smooth and controlled migrations.
  • Debugging & Global Event Catching: Utilizes Tracy for debugging and catching global events, providing detailed error reports and insights.
  • Cron job scheduler: Schedules and manages cron jobs using peppeocchi/php-cron-scheduler, automating repetitive tasks.
  • Dependency Injection: Facilitates dependency management using Sukarix's own DI container, promoting loose coupling and testability.
  • Inversion of Control: Implements IoC using Sukarix, ensuring modular and maintainable code.
  • Bash tool: A forthcoming feature in Sukarix for creating and managing bash scripts, enhancing CLI capabilities.

Understanding Fat-Free Framework

Introduction

Fat-Free Framework (F3) is a powerful yet lightweight PHP framework designed to help developers build dynamic web applications quickly and efficiently. One of the core concepts in F3 is the "Hive," which is a centralized place where the framework stores and manages all application data.

The Hive and F3 Class

The Hive

The Hive is a key-value store that acts as the central repository for all configuration settings, routing information, session data, and more. It is accessible throughout the application, making it easy to manage and retrieve necessary data from anywhere in your code.

The F3 Class

The F3 class is a singleton, meaning there is only one instance of this class throughout the application's lifecycle. This singleton instance is accessible from anywhere in your application, providing a consistent and centralized way to interact with the framework's core functionalities.

How It Works

  1. Initialization: When the application starts, the F3 singleton is created and the Hive is initialized with system variables and configurations.
  2. Routing: F3 uses the Hive to manage routes, mapping URLs to specific functions or controllers.
  3. Session Management: The framework uses the Hive to store and manage session data, ensuring user states are maintained across different requests.
  4. Configuration: All configuration settings are stored in the Hive, making it easy to adjust and retrieve settings as needed.
  5. Template Rendering: F3’s template engine uses the Hive to access variables and directives needed to render views dynamically.

More Resources

To dive deeper into how Fat-Free Framework works and to explore its extensive features, refer to the following resources:

User Guide

For a comprehensive understanding of F3, including installation, basic usage, and advanced features, consult the User Guide.

API Reference

The API Reference provides detailed information on all the classes, methods, and properties available in F3, making it an essential resource for developers looking to utilize the framework to its fullest potential.

System Variables

System variables are predefined variables that F3 uses to manage various aspects of the application. For a quick reference on these variables, check out the System Variables page.

Template Directives

F3's template engine comes with a set of powerful directives that make it easy to render dynamic content. You can find a list of these directives and how to use them on the Template Directives page.

By leveraging these resources, you can gain a thorough understanding of the Fat-Free Framework and harness its full potential to build efficient, scalable, and robust PHP applications.

Instructions for a new Sukarix application

Introduction

To set up your Sukarix application with Vagrant follow these steps:

Step 1: Create a new Sukarix project

Run the following command to create a new Sukarix project using Composer:

composer create-project sukarix/application

Using development version

It is also possible to create a new Sukarix project using the current development version of the framework by adding --stability=dev to the command.

composer create-project --stability=dev sukarix/application

Step 2: Navigate to the project directory

Once the project is created, navigate to the project directory:

cd application

Step 3: Initialize vagrant

The Sukarix project includes a Vagrant setup to help streamline the development environment. Initialize Vagrant by running:

vagrant up

This command will set up the Vagrant environment and automatically install PostgreSQL and Redis.

Step 4: Access the Application

After the Vagrant setup is complete, the application will be accessible via:

http://sukarix.test

Configuration Details

  • PostgreSQL and Redis are installed by default in the current version of the Sukarix project.
  • Ensure your local environment is configured to handle .test domains (you might need to adjust your hosts file if necessary).

Accessing the Application

After running vagrant up, you can access your application at http://sukarix.test. If you encounter issues accessing the site, ensure your system's hosts file includes the correct entry, typically something like:

192.168.56.100  sukarix.test

Configuration

Configuration Files

Sukarix is configured via .ini files by default, allowing for clear and manageable settings. The configuration load order ensures that settings can be overridden based on the environment.

Configuration Load Order

  1. Base Configuration:

    • config/classes.ini
    • config/default.ini
  2. Additional Configurations:

    • Files listed in the CONFIGS variable, e.g., smtp, notifications, upload. No need to add .ini extension.
    • config/validation.ini (loaded only when a data validation request is initiated).
  3. Environment-Specific Configuration:

    • config/config-<environment>.ini
  4. Routing and Access Control:

    • config/routes.ini
    • config/routes-<environment>.ini
    • config/access.ini or config/access-cli.ini (based on environment).

Dynamic reconfiguration

Configuration changes are automatically reloaded, meaning there is no need to restart any service.

Automatic .ini Extension Handling

When specifying additional configuration files in the CONFIGS variable, you do not need to include the .ini extension. Sukarix will automatically append .ini to the file name during the loading process. For example, if you set CONFIGS=notifications,smtp,upload, Sukarix will load config/notifications.ini, config/smtp.ini, and config/upload.ini.

Environment Overrides

Any configuration setting can be overridden in the environment-specific .ini file (config/config-<environment>.ini). This allows for tailored configurations depending on whether the application is in development, testing, or production.

Default Configuration Example

Here is an overview of the default settings found in default.ini:

  • Global Settings:

    • DEBUG: Stack trace verbosity.
    • PACKAGE: Display name in requests.
    • LOGS: Custom log location.
    • TEMP: Temporary folder for cache and compiled templates.
    • UPLOADS: Directory for file uploads.
    • UI: Paths for user interface files.
    • LOCALES: Location of language dictionaries.
    • ENCODING: Default character encoding.
    • LANGUAGE: Active language.
    • FALLBACK: Fallback language.
  • Cache and Minification:

    • CACHE: Cache configuration.
    • SEED: Cache seed.
    • MINIFY_JS and MINIFY_CSS: Toggle minification.
  • Timezone and Environment:

    • TZ: Timezone setting.
    • application.environment: Current environment.
    • log.session: Log session queries.
    • session.table: Table for session storage.
    • pagination.limit: Default pagination limit.
    • template.default: Default view to render.
    • log.keep: Log retention period.
    • server.host: Host for command-line actions.
    • error.channel: Error notification channel.
  • Security:

    • csrf.enabled: Enable or disable CSRF protection.
    • csrf.expiry: CSRF token expiry time in seconds.

Directory Structure

Structure

Understanding the directory structure of a Sukarix application is crucial for effective development and maintenance. Below is an overview of the typical directory layout and the purpose of each directory and file.

app
├── config
│   ├── access.ini
│   ├── access-cli.ini
│   ├── classes.ini
│   ├── config-development.ini
│   ├── config-test.ini
│   ├── default.ini
│   ├── notifications.ini
│   ├── routes.ini
│   ├── routes-cli.ini
│   ├── routes-test.ini
│   ├── smtp.ini
│   ├── upload.ini
│   ├── validation.ini
├── i18n
├── src
├── templates
data
db
├── data
├── migrations
├── seeds
logs
public
├── css
├── js
├── index.php
├── minified
uploads
tmp
├── mail
test
vendor
.php-cs-fixer
phinx.yml

Directory and File Descriptions

app

This is the main application directory containing configuration files, source code, templates, and localization files.

config

Contains various configuration files for the application.

  • access.ini: Defines access control rules for web applications.
  • access-cli.ini: Defines access control rules for CLI applications.
  • classes.ini: Configuration for class mappings and dependencies.
  • config-development.ini: Configuration specific to the development environment.
  • config-test.ini: Configuration specific to the test environment.
  • default.ini: Default configuration settings.
  • notifications.ini: Settings for notifications (e.g., email, chat integrations).
  • routes.ini: Defines routes for web applications.
  • routes-cli.ini: Defines routes for CLI applications.
  • routes-test.ini: Defines routes for test environments.
  • smtp.ini: Configuration for SMTP settings.
  • upload.ini: Settings for file uploads.
  • validation.ini: Configuration for data validation.

i18n

Directory for internationalization (i18n) files, containing localization strings for different languages.

src

Contains the source code for the application, including controllers, models, and other classes.

templates

Directory for template files used by the application. These are typically .phtml files that define the HTML structure and content.

data

Directory for storing the SQLite database files.

db

Contains database-related files and directories.

  • data: Directory for storing the SQLite database files.
  • migrations: Directory for database migration scripts.
  • seeds: Directory for database seed files.

logs

Directory for log files generated by the application.

public

The web root directory containing publicly accessible files.

  • css: Directory for CSS files.
  • js: Directory for JavaScript files.
  • index.php: The entry point for the application.
  • minified: Directory for minified JavaScript and CSS files.

uploads

Directory for user-uploaded files.

tmp

Directory for temporary files.

  • mail: Directory for emails sent in development and test environments, stored as files.
  • cache: Directory for cache files.

test

Directory for unit tests and testing-related files.

vendor

Directory for Composer dependencies.

.php-cs-fixer

Configuration file for PHP-CS-Fixer, a tool for automatically fixing PHP coding standards issues.

phinx.yml

Configuration file for Phinx, a PHP database migration tool.

This directory structure helps to keep your application organized and maintainable, ensuring that related files and configurations are logically grouped together.

Terminology

Hive

A central place where Fat-Free Framework (F3) stores and manages application data, including configuration settings, routing, and session information. The Hive acts as a global registry, making data accessible throughout the application.

Configuration File

Refers to any ini configuration file used to define application settings and dependencies. This file helps in managing the application's configuration in a structured and centralized manner.

Action

Refers to action-wise micro-controllers inspired by ForkCMS. These are responsible for handling specific tasks or requests within the application, typically mapped to routes and executed to perform a particular function.

Bootstrapping

The application initialization phase where the framework, akin to the kernel in other frameworks, loads configurations, sets up the environment, and prepares the application for handling requests.

Environment

The automatically detected application environment, which can be test, development, or production. This setting can be overridden to suit specific needs during development or deployment.

Injector

A component responsible for injecting and initializing Inversion of Control (IoC) classes defined in the configuration file. It manages dependencies and ensures that required services are available throughout the application.

Processor

A component responsible for applying behaviors or traits to classes. It ensures that specific functionalities or attributes are consistently applied across relevant classes.

Session

The class responsible for managing user sessions, including session creation, data storage, and session termination.

ErrorChannel

The global exception handling component used to manage and route errors. It supports multiple channels like Zulip and email for notifying about exceptions.

User Role

Defines the various roles within the application, such as visitor, admin, customer, or api user. These roles determine the level of access and permissions for different parts of the application.

Assets

The class responsible for injecting JavaScript and CSS assets into views, either from the action or directly within the view itself.

View

Refers to the F3 template view files, typically ending with .phtml, used to render the user interface.

Flash

Contains notifications to be displayed in the frontend. It manages temporary messages that inform users about the status of their actions.

I18n

The class that contains different types of messages depending on the localization settings. It supports internationalization and helps manage translations.

MailSender

The class responsible for sending emails within the application. It handles email composition, configuration, and delivery.

Model

A Cortex class with additional behaviors, used to represent and manage the application's data layer. It includes ORM features for interacting with the database.

Notifier

The component responsible for sending notifications to third parties, such as Zulip, Slack, or email, ensuring that important events are communicated effectively.

Constraints

The class responsible for validating data inputs within the application. It ensures that data conforms to specified rules and constraints before processing.

Tailored

The Tailored class is a singleton that extends F3's \Prefab, ensuring only one instance of the class exists. It has the ability to glue trait behaviour to a class while maintaining its singleton nature and integrating it into the dependency injection registry.

Template Directive

Directives used within F3 templates to insert dynamic content, control flow, and manage template inheritance. These directives allow developers to create flexible and reusable templates for rendering views. For a detailed list and explanation of template directives, refer to the F3 Quick Reference.

Application Lifecycle

Entry-point

The entry point for a Sukarix application is public/index.php.

This is where initial detection happens to determine if unit tests need to be run in the browser, a process that will be covered in detail later.

Once the Application is instantiated, the following steps occur:

1. Detect if the Application is Running in CLI Mode

The application first checks if it is being executed from the command line (CLI) or through a web server. This allows for conditional loading of CLI-specific configurations and behaviors.

2. Create an Instance of the Fat-Free Framework (F3) Singleton Class

An instance of the F3 singleton class is created. This instance acts as the central hub for managing application configuration, routing, and other core functionalities.

3. Set Up PHP Variables

The application sets up necessary PHP variables, including error reporting levels, timezone settings, and memory limits, to ensure a consistent execution environment. Up to the developer to override it.

4. Automatically Detect the Application Environment

The application detects the current environment (test, development, or production). This setting can be overridden if needed, and it dictates how the application behaves, including error reporting and debugging levels.

5. Load the Configuration Files

The application loads its configuration settings from ini configuration files. These files define various parameters and settings required for the application's operation.

6. Set Up Logging

Logging is set up to capture and record important events, errors, and performance metrics. This is crucial for monitoring the application and diagnosing issues.

7. Add the Global Exception Handler

A global exception handler is added to catch and manage any unhandled exceptions, ensuring that errors are logged and appropriate responses are provided without crashing the application.

8. Connect to the Database

The application establishes a connection to the database using the settings defined in the configuration files. This connection is essential for data storage and retrieval.

9. Prepare the Session

The session handler is initialized to manage user sessions, including creating, storing, and terminating sessions. This is important for maintaining user state across requests.

10. Load Additional Application Settings

Additional settings and configurations specific to the application are loaded. These can include custom parameters, feature toggles, and other application-specific settings.

11. Load Additional CLI Configuration if CLI Mode is Detected

If the application is running in CLI mode, additional configurations specific to the command-line environment are loaded. This ensures that CLI commands have the necessary settings and resources.

12. Load Routing and Access Control Lists (ACL)

The routing configuration and ACLs are loaded to define how incoming requests are handled and to enforce access permissions. This ensures that routes are correctly mapped to actions and that users have appropriate access rights.

13. Execute the Start Function

The start function of the application is executed, which in turn calls the F3 run function. This kicks off the application, allowing it to handle incoming requests or execute CLI commands.

14. Log Performance Metrics and Finish

Finally, the application logs performance metrics for the entire lifecycle process. This includes timing information and resource usage statistics, which are useful for performance monitoring and optimization.

This comprehensive sequence ensures that the Sukarix application is thoroughly initialized, configured, and prepared to handle both web requests and CLI commands efficiently and reliably.

Dependency Injection

Overview

Dependency Injection in Sukarix is facilitated through the singleton class Injector::instance()->get('access'). This method allows for easy and efficient management of dependencies within your application.

Example Usage

In this example, access is the default ACL Middleware tied to f3-access:

$access = Injector::instance()->get('access');

Additionally, the Injector can find an object from its class directly:

$multiLang = Injector::instance()->get(\Multilang::class);

Configuration & Default Dependencies

These default classes can be easily changed or overridden by updating the classes.ini file. The default configuration is in the table below:

KeyClass
mailerSukarix\Mail\MailSender
notifierSukarix\Notification\Notifier
sessionSukarix\Core\Session
i18nSukarix\Helpers\I18n
assetsSukarix\Helpers\Assets
access\Access
eventsSugar\Event
template\Template
htmlSukarix\Helpers\HTML
multi_language\Multilang
receiverSukarix\Helpers\Receiver

Creating Injectable Singletons

For classes that should be singletons with behaviors, they must extend the Sukarix\Core\Tailored class. This ensures the framework can automatically integrate their behaviors. More details on these behaviors can be found in the Behaviors section of the documentation.

Instantiating an injectable singleton object

There is no need to manually instantiate the injected object, Sukarix will do it for you.

Storing DI Classes

The F3 \Registry class is used to store these dependency-injected classes, ensuring they are easily accessible throughout your application. However, it is recommended to use the Injector class that already wraps this functionality, as it provides additional features and should be preferred over direct usage of \Registry.

Routing and Access Control

Introduction

Sukarix leverages the powerful routing and access control capabilities of the Fat-Free Framework (F3) to manage web and CLI application routes. The configuration for routing and access control is handled through routes.ini and access.ini for web applications, and routes-cli.ini and access-cli.ini for CLI applications. Additionally, multi-language routing is supported via f3-multilang.

Routing

Concepts

Routing in Sukarix allows you to map URLs to specific actions in your application. This is managed through configuration files where you define patterns for web and CLI routes. Key concepts include:

  • HTTP Methods: Define the HTTP methods (GET, POST, PUT, DELETE, etc.) that the route will respond to.
  • Route Aliases: Provide named routes for easier reference.
  • Tokens: Use tokens to capture parts of the URL (e.g., /users/@id).
  • Modifiers: Use [ajax] for AJAX requests and [cli] for CLI routes.
  • Asterisk (*): Use wildcards to match any subpath.
  • Named Routes: Assign names to routes for easy referencing.
  • Rerouting: Redirect requests to different routes or actions.
  • ReST: Implement RESTful APIs using standard HTTP methods.
  • Multi-language Routing: Support multiple languages using f3-multilang.

Web Application Routing (routes.ini)

In Sukarix, routes for web applications are defined in the routes.ini file.

Example Configuration

[routes]
; default route
GET      @home        : /                          = Actions\Core\Main->execute
GET      @docs        : /docs/*                    = Actions\Core\Docs->execute
POST|PUT @set_locale  : /set-locale/@locale [ajax] = Actions\Account\SetLocale->execute
DELETE   @user_delete : /users/@id                 = Actions\Users\Delete->execute

Explanation

  • GET @home : / = Actions\Core\Main->execute

    • GET: The HTTP method for the route.
    • @home: The route alias.
    • /: The URL pattern for the home page.
    • = Actions\Core\Main->execute: The action and method that handle the request.
  • GET @docs : /docs/* = Actions\Core\Docs->execute

    • GET: The HTTP method for the route.
    • @docs: The route alias.
    • /docs/*: The URL pattern with a wildcard to match any subpath.
    • = Actions\Core\Docs->execute: The action and method that handle the request.
  • POST|PUT @set_locale : /set-locale/@locale [ajax] = Actions\Account\SetLocale->execute

    • POST|PUT: The HTTP methods for the route.
    • @set_locale: The route alias.
    • /set-locale/@locale: The URL pattern with a token (@locale).
    • [ajax]: Modifier indicating the route should handle AJAX requests.
    • = Actions\Account\SetLocale->execute: The action and method that handle the request.
  • DELETE @user_delete : /users/@id = Actions\Users\Delete->execute

    • DELETE: The HTTP method for the route.
    • @user_delete: The route alias.
    • /users/@id: The URL pattern with a token (@id).
    • = Actions\Users\Delete->execute: The action and method that handle the request.

CLI Application Routing (routes-cli.ini)

In Sukarix, routes for CLI applications are defined in the routes-cli.ini file.

Example Configuration

[routes]
; route to the main task scheduler
GET @run_job : /cli/jobs/run       [cli] = Actions\Jobs\TaskScheduler->execute
GET @logs_clean : /cli/logs/clean     [cli] = Sukarix\Actions\Logs\Clean->execute
GET @sessions_clean : /cli/sessions/clean [cli] = Sukarix\Actions\Core\SessionsClean->execute

Explanation

  • GET @run_job : /cli/jobs/run [cli] = Actions\Jobs\TaskScheduler->execute

    • GET: The HTTP method for the route.
    • @run_job: The route alias.
    • /cli/jobs/run: The URL pattern for running jobs.
    • [cli]: Modifier indicating the route is for CLI mode.
    • = Actions\Jobs\TaskScheduler->execute: The action and method that handle the request.
  • GET @logs_clean : /cli/logs/clean [cli] = Sukarix\Actions\Logs\Clean->execute

    • GET: The HTTP method for the route.
    • @logs_clean: The route alias.
    • /cli/logs/clean: The URL pattern for cleaning logs.
    • [cli]: Modifier indicating the route is for CLI mode.
    • = Sukarix\Actions\Logs\Clean->execute: The action and method that handle the request.
  • GET @sessions_clean : /cli/sessions/clean [cli] = Sukarix\Actions\Core\SessionsClean->execute

    • GET: The HTTP method for the route.
    • @sessions_clean: The route alias.
    • /cli/sessions/clean: The URL pattern for cleaning sessions.
    • [cli]: Modifier indicating the route is for CLI mode.
    • = Sukarix\Actions\Core\SessionsClean->execute: The action and method that handle the request.

Multi-language Routing

Sukarix supports multi-language routing using f3-multilang. This allows you to define routes that adapt to different languages.

Configuration Example

[MULTILANG.languages]
en = en-GB
fr = fr-FR
ar = ar-AR
es = es-ES

[MULTILANG]
global = locale,/cli
  • [MULTILANG.languages]: Defines the languages and their respective locale codes.
  • [MULTILANG]: Specifies global aliases that are not localized by default.

Access Control

Access control in Sukarix is managed through access.ini and access-cli.ini files, defining policies and rules for both web and CLI applications.

Web Application Access Control (access.ini)

Sukarix uses the access.ini file to manage access control for web applications. The configuration defines policies and rules for access control using the F3-Access component.

Example Configuration

[ACCESS]
; deny all routes by default
policy = deny

[ACCESS.rules]
; Routes allowed to all type of users
deny  *      /* = *
allow GET    @home = *
allow GET    @docs = admin,customer
allow        @set_locale = *
allow DELETE @user_delete = admin

Explanation

  • policy = deny

    • Sets the default policy to deny access to all routes.
  • deny * /* = *

    • Denies access to all users for all routes by default.
  • allow GET @home = *

    • Allows access to the home route (@home) for all users.
  • allow GET @docs = admin,customer

    • Allows access to the documentation route (@docs) only for admin and customer roles.
  • allow @set_locale = *

    • Allows access to the set locale route (@set_locale) for all users.
  • allow DELETE @user_delete = admin

    • Allows access to delete user route (@user_delete) only for admin role.

CLI Application Access Control (access-cli.ini)

Sukarix uses the access-cli.ini file to manage access control for CLI applications.

Example Configuration

[ACCESS]
; allow all routes by default
policy = allow

Explanation

  • policy = allow
    • Sets the default policy to allow access to all CLI routes.

References

For more detailed information on F3's routing and access control mechanisms, refer to the following resources:

Framework Variables

Fat Free Framework Variables

Detailed information on Fat-Free Framework variables can be found here.

Globals

Global variables and their usage are explained here.

Naming Rules

Naming conventions are outlined here. Sukarix follows these rules, using capital letters when possible. If F3 extensions deviate from this rule, they are used as is.

Sukarix Framework Variables

Fat-Free Framework system variables are listed here.

Example Sukarix framework variables:

MINIFY_JS

boolean     Default: TRUE in production configuration

Turns JavaScript minification on or off. Should be environment dependant.

MINIFY_CSS

boolean     Default in template application: TRUE in production configuration

Turns CSS minification on or off. Should be environment dependant.

CONFIGS

string     Default in template application: smtp,notifications,upload

List of configuration files to load.

application.environment

string

Sets the application environment (e.g., development, testing).

Sukarix Convention: Environment auto-detection

If the server hostname ends with .test the application.environment variable will automatically be set to development.

template.default

string     Default in template application: website

Default view to render.

log.keep

integer     Default in template application: 14

Days to keep logs before cleanup.

server.host

string     Default: NULL

Server host for command line actions.

error.channel

string     Default: NULL

Error notification channel ("email" or "zulip").

Databases Management

Database Configuration

For configuring database access, the framework follows the guidelines outlined by the Fat-Free Framework. This includes setting up database connections and handling queries efficiently.

Cortex ORM

The framework utilizes Cortex ORM for object-relational mapping, simplifying interactions with the database. For detailed usage and configuration instructions, refer to the Cortex documentation.

Database Migrations

Database migrations are managed using the Phinx library, which is included in the template application with a phinx.json file. This file can be customised, although Phinx is the recommended tool. Comprehensive documentation for Phinx is available here.

Model Class

The Model class provides a structured way to access data using Cortex ORM. It includes methods for pagination, data conversion, and change detection, ensuring robust and efficient data handling.

Sukarix Convention: Model timestamps

The Model class follows conventions for managing timestamps:

  • created_on: Automatically set when a record is created.
  • updated_on: Automatically updated when a record is modified.

File Upload

Introduction

The Receiver class in Sukarix is designed to handle file uploads efficiently. It provides methods for saving uploaded files and preparing upload directories, ensuring that your application can manage file uploads seamlessly.

Configuration

To use the Receiver class, you need to configure it in the classes.ini file:

receiver = \Helpers\Receiver

Methods

saveUploadedFile

This method saves the uploaded file to the specified destination. It checks the environment to decide whether to use rename or move_uploaded_file for saving the file.

prepareUploadDirectory

This method prepares the upload directory by creating it if it does not exist. It throws a RuntimeException if the directory cannot be created.

Example Usage

To use the Receiver class for handling file uploads, you can get an instance from the Injector and use the \Web::instance()->receive method to process the uploaded files.

/**
 * @var Receiver $receiver
 */
$receiver = Injector::instance()->get('receiver');

\Web::instance()->receive(static function(&$file, &$formFieldName) use (&$action, &$receiver) {
    if (0 === $file['size']) {
        return false;
    }
    
    $uploadDirectory = 'path/to/upload/directory';
    $receiver->prepareUploadDirectory($uploadDirectory);
    
    $destination = $uploadDirectory . '/' . $file['name'];
    return $receiver->saveUploadedFile($file, $destination);
});

The Receiver class ensures that file uploads are handled efficiently and securely, with proper directory preparation and file movement based on the environment. This setup allows for easy management of uploaded files in your Sukarix application.

Data Validation

Human-readable data validation syntax

Form validation is a crucial part of building robust web applications. Sukarix simplifies this process by allowing you to declare your validation rules in an easy-to-read configuration file. This page provides an overview of how to use Sukarix's data validation capabilities.

Configuration

Validation rules are declared in an INI file. Here's an example:

[CONSTRAINTS.users.edit]
email = email
username = length:4,32
role = in:Enum\UserRole
status = in:Sukarix\Enum\UserStatus

Using the Validator

To validate data, use the Constraints class in your controller or model. Below are various examples demonstrating different usages.

Example: Basic Usage

public function save($f3, $params): void
{
    $form = $this->getDecodedBody();

    Constraints::instance()->verify($form, 'users.edit');

    // Process the validated data
}

Example: Multiple Rulesets

You can validate against multiple rulesets by separating them with a pipe (|).

public function save($f3, $params): void
{
    $form = $this->getDecodedBody();

    Constraints::instance()->verify($form, 'settings.save.default|users.edit');

    // Process the validated data
}

You can also pass ruleset names as an array.

public function save($f3, $params): void
{
    $form = $this->getDecodedBody();

    Constraints::instance()->verify($form, ['settings.save.default', 'users.edit']);

    // Process the validated data
}

Example: Individual Checks

You can also perform individual checks using the check method.

$filePath = '/path/to/file.css';
Constraints::instance()->check($this->f3->get('ROOT') . $filePath, 'file', true, 'css_file');

How Validation Works

  1. Audit Class:

    • If available, validation rules are first checked in the Audit class.
  2. Constraints Class:

    • If the rule is not found in the Audit class, it falls back to the Constraints class.
  3. Custom Validator:

    • If the rule is not found in the Constraints class, it checks for a user-defined validator class specified in the VALIDATOR configuration property.

Validation rule names are case insensitive

Validator names are case insensitive, meaning notempty, notEmpty, NotEmpty, and NOTEMPTY are treated the same.

Available Validation Rules

Here is a list of available validation rules that you can use in your INI configuration file or directly in your code:

  • email: Validates that the input is a valid email address.
  • length:min,max: Validates that the input length is between min and max.
  • in:Enum\ClassName: Validates that the input is one of the values in the specified enumeration.
  • notEmpty: Validates that the input is not empty.
  • file: Validates that the input is a valid file path.

Example: Custom Validator

You can define custom validation rules in your own validator class and configure Sukarix to use it.

class CustomValidator
{
    public static function isCustom($value)
    {
        // Custom validation logic
        return $value === 'custom';
    }
}

// Usage
$customRules = [
    'custom_field' => 'custom'
];

Constraints::instance()->verifyRules($form, $customRules, true);

Error Handling

When validation fails, the verify method throws an exception if the throwOnFail parameter is set to true.

try {
    Constraints::instance()->verify($form, 'users.edit', true);
} catch (\RuntimeException $e) {
    echo "Validation failed: " . $e->getMessage();
}

To get all validation errors, use the getErrors method.

$errors = Constraints::instance()->getErrors();
print_r($errors);

Combining Validators

You can combine multiple validation rules using the pipe (|) separator.

[CONSTRAINTS.users.edit]
email = email
username = length:4,32|notEmpty
role = in:Enum\UserRole|notEmpty
status = in:Sukarix\Enum\UserStatus|notEmpty
public function save($f3, $params): void
{
    $form = $this->getDecodedBody();

    Constraints::instance()->verify($form, 'users.edit');

    // Process the validated data
}

Session

Session Management

Session handler documentation can be found here.

By default, sessions are stored in the database but can be configured to use the cache system. This allows session data to be debuggable in non-production environments, while in production, storing sessions in cache enhances performance.

Issues with storing sessions in transactional database

Storing a session in the database can be problematic when using transactions, as the database connection is tied to that session. Rolling back or failing a transaction may result in failed updates to the session data. It's important to carefully consider this when designing your application's session management strategy.

Session Functions

The session management system includes the following functions:

  • authorizeUser: Authorizes a user and initiates their session.
  • revokeUser: Revokes a user's session and logs them out.
  • getRole: Retrieves the role of the current user.
  • isRole: Checks if the current user has a specific role.

Logging

Introduction

The framework uses Monolog by default for logging. To enable logging, use the LogWriter behavior trait in your class.

Initializing LogWriter

If the class does not extend the Tailored singleton class, ensure to call the initLogWriter method in the constructor.

Logging Naming Conventions

Logs follow these naming patterns:

  • Application Logs: app-yyyy-mm-dd.log
  • Application Error Logs: app-error-yyyy-mm-dd.log
  • CLI Logs: cli-yyyy-mm-dd.log
  • CLI Error Logs: cli-error-yyyy-mm-dd.log
  • Exception Logs: exception.log

Log Rotation

Logs are kept for 14 days by default, configurable via the log.keep setting (an integer in days). The Sukarix\Actions\Action\Clean action is responsible for rotating and cleaning logs.

Debugging

Introduction

Sukarix uses the Tracy library for debugging. Tracy offers powerful tools to help you debug your applications efficiently.

Basic Usage

To use Tracy, simply call the following functions in your code:

  • Dumping Variables:
    • dump($variable) or dumpe($variable)
    • Debugger::dump($variable)
    • Debugger::barDump($variable)

For more detailed usage and advanced features, refer to the Tracy documentation.

Emails

MailSender Class

The MailSender class in Sukarix is used to send emails with a predefined template. The primary method for sending emails is send(), which has the following signature:

send($template, $vars, $to, $title, $subject): bool

Method Parameters

  • $template: The name of the email template, which must be located in the /mail folder.
  • $vars: An array of variables to be used within the template.
  • $to: The recipient's email address.
  • $title: The title of the email.
  • $subject: The subject line of the email.

Usage Example

Here’s how you might use the send() method to send an email:

/**
 * @var MailSender $mailSender
 */
$mailSender = Injector::instance()->get('mailer');
$template = 'welcome';
$vars = ['name' => 'John Doe', 'link' => 'https://example.com'];
$to = 'johndoe@example.com';
$title = 'Welcome to Our Service';
$subject = 'Getting Started with Our Service';

$mailSender->send($template, $vars, $to, $title, $subject);

This example sends a welcome email using the welcome template, passing in the recipient’s name and a link to be used within the email body.

Notifications

Notifier Class

The Notifier class in Sukarix is designed to send notifications about exceptions that occur in the application. This class extends the Tailored class and uses the HasF3 and LogWriter traits.

Methods

notifyException

The notifyException method is responsible for sending an exception notification. It generates a unique error ID, creates a notification message, and sends it to a specified Zulip stream.

Method Signature:

public function notifyException($exception): void

Parameters:

  • $exception: An instance of \Exception containing the exception details to be notified.

Usage

Here is an example of how to use the notifyException method:

/**
 * @var Notifier $notifier
 */
$notifier = Injector::instance()->get('notifier');
try {
    // Code that may throw an exception
} catch (\Exception $e) {
    $notifier->notifyException($e);
}

Configuration

Ensure the following configuration settings in your .ini file:

[globals]
; error notification channel "email" or "zulip"
error.channel = zulip

[NOTIFICATIONS.zulip]
token = "your-zulip-token"
mail = "your-zulip-email"
uri = "your-zulip-uri"
stream = "your-zulip-stream"
topic = "your-zulip-topic"

Translation / i18n

Localisation Helper Class

The I18n class in Sukarix provides methods to retrieve localized strings from different translation tables. There are four types of translation tables:

  1. Labels (i18n.label)
  2. Messages (i18n.message)
  3. Errors (i18n.error)
  4. Lists (i18n.list)

Methods

lbl

Fetches a localized label.

public function lbl($key): string

msg

Fetches a localized message.

public function msg($key): string

err

Fetches a localized error message.

public function err($key): string

lst

Fetches a localized list.

public function lst($key): array

Example Usage

$i18n = Injector::instance()->get('i18n');
echo $i18n->lbl('welcome'); // Fetches the 'welcome' label
echo $i18n->msg('greeting'); // Fetches the 'greeting' message
echo $i18n->err('not_found'); // Fetches the 'not_found' error message
print_r($i18n->lst('countries')); // Fetches the 'countries' list

locales.js

The locales.js file handles loading and switching of localisation data in JSON format.

Functions

  • loadLocale: Loads the locale data from a JSON file.
  • init: Initializes the locale settings and language menu.
  • initLanguageMenu: Sets up the language selection menu.
  • setLocale: Sets the current locale.
  • switchLocale: Switches to the selected locale and updates the displayed strings.
  • translaterStrings: Updates all strings in the document with localized content.
  • get: Retrieves a localized string based on type, module, and key.
  • err: Retrieves a localized error message.
  • lbl: Retrieves a localized label.
  • loc: Retrieves a localized string.
  • msg: Retrieves a localized message.
  • lst: Retrieves a localized list item.

Example Usage in locales.js

Locale.init(); // Initializes the locale settings
Locale.setLocale('en-GB'); // Sets the current locale to 'en-GB'
Locale.switchLocale('fr-FR'); // Switches to 'fr-FR' and updates the displayed strings

Routing for JSON localisation

The routing for generating JSON localisation files is defined as follows:

GET @locale: /locale/json/@locale.json = Sukarix\Actions\Core\GetLocale->execute

Caching

JSON locale data is cached whenever the translation file is updated to improve performance and reduce load times.

Behaviours

Introduction

Behaviours in Sukarix are traits that can be plugged into classes to extend their functionality. By convention, an init<TraitName> method should be implemented and is called immediately after the injector creates an instance of the class using the trait.

Example Behaviours

  1. LogWriter

    • Description: Enables the implementing class to write to the application logs.
    • Usage:
      class MyClass {
          use LogWriter;
      
          public function initLogWriter() {
              // Initialization code for LogWriter
          }
      }
      
  2. HasF3

    • Description: Injects the $f3 property into the class, providing access to the Fat-Free Framework instance.
    • Usage:
      class MyClass {
          use HasF3;
      
          public function initHasF3() {
              // Initialization code for HasF3
          }
      }
      

Singleton Classes

Any singleton class inheriting from Tailored will have the init<TraitName> methods called by default. This ensures that all behaviours are initialised properly without additional code.

Non-Singleton Classes

If a class does not inherit from Tailored, it must call Processor::instance()->initialize($this); in the constructor to ensure that the init<TraitName> methods are called.

Example Usage

Here’s how you might use these behaviours in a class:

class MyService {
    use LogWriter;
    use HasF3;

    public function __construct() {
        Processor::instance()->initialize($this); // Initialise traits manually
    }

    public function logSomething() {
        $this->log->write('Logging something!');
    }

    public function getFrameworkInstance() {
        return $this->f3;
    }
}

In this example, MyService uses both the LogWriter and HasF3 traits. Since it does not extend Tailored, it explicitly calls Processor::instance()->initialize($this); in the constructor to ensure that the traits are initialised.

CRON / Task Scheduling

TaskScheduler

TaskScheduler is an Action in Sukarix designed for task scheduling. The CLI toolbox installs it as a cron job by default, utilizing the GO\Scheduler syntax.

Default Configuration

The route-cli.ini file contains the default route for task scheduling:

[routes]
; route to the main task scheduler
GET @run_job : /cli/jobs/run [cli] = Actions\Jobs\TaskScheduler->execute

Setting Up Cron

The default cron job should contain:

* * * * * /usr/bin/php /var/www/sukarix/public/index.php "/cli/jobs/run"

Defining Jobs

Each job must be defined in route-cli.ini. For example, the default log cleaning job is implemented as:

GET @logs_clean : /cli/logs/clean [cli] = Sukarix\Actions\Logs\Clean->execute

Implementing the Execute Function

The execute function should schedule tasks using the scheduler:

public function execute() {
    // Clean old sessions every 8 hours at 10 minutes after the hour
    $this->scheduler->php($this->documentRoot, null, ['/cli/sessions/clean' => ''], 'sessions-clean')
                    ->onlyOne()
                    ->at('20 */8 * * *');
}

This example schedules a session cleaning task to run every 8 hours at 10 minutes past the hour, ensuring only one instance runs at a time.

Events

Introduction

In Sukarix, events are managed using the Sukarix\Behaviours\HasEvents trait. This allows any class to emit and handle events throughout the application using the Sugar Events system integrated with the PHP Fat-Free Framework.

Key Features of Sugar Events

  • Emit events from any point in your application
  • Attach multiple listeners to an event with priority
  • Local events on specific objects
  • Send payload and context data with events
  • Support for sub-events and event propagation
  • Stop the event chain
  • Works with F3 v3.5 and PHP v7.2+

Example Usage

Initializing Events

To initialize the event system and get the global Event instance:

$events = \Sugar\Event::instance();

Defining a Listener

You can define a listener (or hook) to an event using a typical F3 callstring, callback, or callable:

$events->on('user_login', 'Notification->user_login');
$events->on('user_login', function() {
  // ...
});
$events->on('user_login', [$this, 'method']);

Emitting an Event

To emit an event and notify all listeners:

$events->emit('user_login');

Sending Payload with Event

You can send additional data (payload) with an event:

$events->on('user_login', function($username) {
  \Logger::log($username . ' logged in');
});
$events->emit('user_login', 'freakazoid');

Multiple Listeners with Prioritization

Listeners can be prioritized; higher numbers are called first:

$events->on('user_login', function($username) {
  \Logger::log($username . ' logged in');
}, 10);
$events->on('user_login', function() {
  \Flash::addMessage('You have logged in successfully');
}, 20);
$events->emit('user_login', 'freakazoid');

Stopping the Event Chain

A listener can stop further listeners from being called:

$events->on('user_login', function($username) {
  \Logger::log($username . ' logged in');
});
$events->on('user_login', function() {
  \Flash::addMessage('You have logged in successfully');
  return false;
}, 20);
$events->emit('user_login', 'freakazoid');

Additional Event Context Data

Send additional context data with an event:

$events->on('user_login', function($username, $context) {
  if ($context['lang'] == 'en')
    \Flash::addMessage('You have logged in successfully');
  elseif ($context['lang'] == 'de')
    \Flash::addMessage('Du hast dich erfolgreich angemeldet');
});
$events->emit('user_login', 'freakazoid', array('lang' => 'en'));

Additional Listener Options

Listeners can have additional options:

$events->on('user_login', function($username, $context, $event) {
  \Flash::addMessage('You have logged in successfully', $event['options']['type']);
}, 20, array('type' => 'success'));

Filtering Payload

Listeners can modify and return the event payload:

$events->on('get_total', function($basket) {
  $sum = 0;
  foreach ($basket as $prod) {
    $sum += $prod;
  }
  return $sum;
});

$products = array('a' => 2, 'b' => 8, 'c' => 15);
$sum = $events->emit('get_total', $products);
echo $sum; // 25

Adding Sub-Events

Sub-events are called after the parent event:

$events->on('get_total.tax', function($sum) {
  return $sum + ($sum * 0.2);
});
$events->on('get_total.shipping', function($sum) {
  return $sum + 5;
});
$sum = $events->emit('get_total', $products);
echo $sum; // 35

Removing Hooks

Remove listeners for specific events:

$events->off('get_total.tax');
$sum = $events->emit('get_total', $products);
echo $sum; // 30

Local Events for Mappers

Support for local events on specific objects:

$user = new \Model\User();
$events->watch($user)->on('update.email', '\Mailer->sendEmailActivationLink');

Error Handling

Introduction

In Sukarix, error handling is managed by a global error handler that can be overridden in the Application class. The default implementation uses Tracy\Debugger for managing errors and handling fatal exceptions. The global exception handling is only active in the production environment.

Default Implementation

The Application class includes a protected method handleException() that sets up the error handler. The default implementation is capable of sending email or Zulip notifications based on the configuration of error.channel. Before sending the email, it stores the exception stack trace in HTML format. It's important to note that the error stack might contain sensitive information, so sending it by default is not enabled.

Additionally, notifications for the same exception hash are sent only once every 24 hours.

Customizing Error Handling

To customize the error handling, you can override the handleException() method in your Application class:

protected function handleException(): void {
    if (Debugger::$productionMode) {
        Debugger::$onFatalError[] = function($exception) {
            // Custom fatal error handling logic
        };
    }
}

Template Engine

Introduction

The template engine in Sukarix is built on top of the Fat-Free Framework's (F3) template engine. It provides a flexible and efficient way to render views, leveraging F3's powerful features while adding enhancements specific to Sukarix.

Template Loading

In Sukarix, templates are loaded into views using a specific pattern. By default, the view files are stored in the templates directory and have a .phtml extension.

Mapping Actions to Templates

Sukarix maps actions to templates by following a convention-based approach. When an action calls $this->render();, it maps to the template based on the namespace and class name, converted to snake_case. For example:

  • Action Class: Actions\Core\Main
  • Mapped Template: templates/actions/core/main.phtml

Default Template Extension

The default template extension in Sukarix is .phtml and is automatically appended.

Example Code

$this->render('commons/api/response');

This method call will automatically render the templates/commons/api/response.phtml when called from any action.

JavaScript and CSS Template Directives

Sukarix adds custom template directives for including JavaScript and CSS files in your views. These directives simplify the process of managing assets.

  • JavaScript Directive:

    <js src="path/to/script.js" type="module"></js>
    

    This directive is used to include JavaScript files in your view. You can pass an optional type attribute, such as "module". If the type attribute is not provided, "text/javascript" will be chosen by default.

  • CSS Directive:

    <css href="path/to/style.css"></css>
    

    This directive is used to include CSS files in your view.

File Validation

The existence of the specified file is validated when the directive attempts to load it. If the file is not found, an exception will be thrown. This ensures that developers can handle missing files during the development phase before deploying to production.

By utilizing these custom directives, Sukarix ensures that assets are managed efficiently and that any issues with missing files are caught early in the development cycle.

F3 Template Directives

F3 provides a set of powerful template directives that make it easy to render dynamic content, control flow, and manage template inheritance. Some of the key directives include:

  • Include Directive:

    <include href="partial.phtml" />
    

    This directive includes another template file within the current template.

  • Repeat Directive:

    <repeat group="{{ @items }}" value="{{ @item }}">
      <!-- Content to repeat -->
    </repeat>
    

    This directive repeats a block of content for each item in a collection.

  • Conditional Directive:

    <check if="{{ @condition }}">
      <!-- Content to show if condition is true -->
    </check>
    

    This directive conditionally renders content based on a boolean expression.

  • Set Directive:

    <set name="variable" value="value" />
    

    This directive sets a variable to a specified value within the template.

  • Session Directive:

    <session name="variable" />
    

    This directive retrieves a value from the session.

  • Cookie Directive:

    <cookie name="variable" />
    

    This directive retrieves a value from cookies.

  • Locale Directive:

    <locale name="variable" />
    

    This directive retrieves a localized value.

Additional Resources

For more detailed information on F3's template engine and directives, you can refer to the F3 Views and Templates Documentation.

Assets

Introduction

Sukarix uses the Assets class to manage and render CSS and JavaScript files efficiently. By default, it looks for CSS files under public/css and JavaScript files under public/js.

Default Storage Locations

  • CSS Files: public/css
  • JavaScript Files: public/js
  • Minified Files: public/minified

The Assets class automatically handles the minification of CSS and JS files and places the minified versions in the public/minified directory.

Default Storage Locations

By default, CSS files are stored in public/css, JavaScript files in public/js, and minified files in public/minified.

Rendering Groups

Sukarix provides two rendering groups named head and footer to organize asset rendering. To render these groups in your template, use:

{{ \Sukarix\Helpers\Assets::instance()->renderGroup('footer') }}

JavaScript Initialization

The Assets class can also call JavaScript functions and initialize them. Example:


<script>
    jQuery(document).ready(function () {
        {{ \Sukarix\Helpers\Assets::instance()->currentJsLocale() }}
        {{ \Sukarix\Helpers\Assets::instance()->setUserRole() }}
        {{ \Sukarix\Helpers\Assets::instance()->initJsClasses() }}
    });
</script>

Example Usage

Adding CSS and JS Files in a View

In your action, you can add CSS and JS files like this:

$this->assets->addJs('core.js');
$this->assets->addJs('core/servers.js');
$this->assets->addJs('vendors/datatables.min.js');
$this->assets->addCss('datatables.min.css');
$f3->push('init.js', 'Servers');

Rendering Assets

To render assets in the head group:

{{ \Sukarix\Helpers\Assets::instance()->renderGroup('head') }}

To render assets in the footer group:

{{ \Sukarix\Helpers\Assets::instance()->renderGroup('footer') }}

By using these functionalities, Sukarix ensures efficient management and rendering of assets, enhancing the performance and maintainability of your web application.

JavaScript

Introduction

The default Sukarix application template includes locale.js, which downloads the session locale using AJAX and provides functions to access localized strings. Additionally, Common.userRole is accessible via JavaScript and is set from the session.

locale.js

locale.js handles the localization of strings in your application. It downloads the session locale and provides easy access to localized strings. This ensures that your application can support multiple languages and dynamically switch between them based on the user's session.

Common.userRole

The Common.userRole variable is set from the session and is accessible via JavaScript. This allows you to manage user roles on the client side and adjust your application's behavior based on the user's role.

Minimalistic Implementation

Sukarix provides this minimalistic implementation, giving developers the flexibility to use modern frontend frameworks as needed. You can integrate libraries and frameworks such as React, Vue, or Angular to build more complex and interactive user interfaces.

Example Usage

Accessing Localized Strings

var welcomeMessage = Locale.msg('welcome');
console.log(welcomeMessage);

Using Common.userRole

if (Common.userRole === 'admin') {
    console.log('User is an admin');
} else {
    console.log('User is not an admin');
}

Users

Introduction

The User Model class in Sukarix is the central class for managing users. It includes user status, roles, and authentication mechanisms.

User Status

User status can be either active or inactive, managed using the Sukarix\Enum\UserStatus enum.

User Roles

Sukarix provides four default user roles:

  • visitor: Default role, represented as * in the routing ACL.
  • admin
  • customer
  • api: A user that can authenticate through HTTP basic authentication.

These roles impact the access control list (ACL) in the configuration and can be extended by developers as needed.

Extending User Roles

Developers can extend user roles by adding new roles to the UserRole enum and updating the ACL configuration accordingly. This allows for greater flexibility and customization to fit the needs of your application.

Authentication

Introduction

Sukarix provides a straightforward method for authenticating users using models and session management. Below are examples and explanations on how to implement authentication and handle user verification in Sukarix.

Authenticating a User

To authenticate a user, retrieve the user model by their email, check their status and role, and verify their password. If all conditions are met, authorize the user in the session.

Example Code

$user = new UserModel();
$user = $user->getByEmail($email);
if (UserStatus::ACTIVE === $user->status && UserRole::API !== $user->role && $user->verifyPassword($password)) {
    $this->session->authorizeUser($user);
}

Authorizing a User

The authorizeUser method is used to authorize a user in the session. This method sets the necessary session variables to mark the user as authenticated.

Verifying API Users

In the Action class, the isApiUserVerified() method checks if a user has authenticated via the HTTP Basic Auth header. This is useful for API endpoints where HTTP Basic Authentication is preferred.

Example Usage

if ($this->isApiUserVerified()) {
    // API user is authenticated
}

Authorisation System

Introduction

The authorisation system in Sukarix is managed through the f3-access library. The documentation for f3-access is available in the f3-access repository.

Access Instance

The access instance is available in classes using the HasAccess behaviour trait. This trait integrates the access control mechanisms provided by f3-access into your Sukarix application.

Default Authorization System

The beforeroute method of the Action class implements the default authorization system. This method checks the user's permissions before allowing access to specific routes or actions.

Security Best Practices

By default, everything is set to deny in the template application for security reasons. This default setting ensures that only explicitly allowed actions are accessible, enhancing the overall security of your application.

CSRF Protection

Overview

Sukarix provides built-in CSRF (Cross-Site Request Forgery) protection mechanisms to ensure the security of your forms and requests. By enabling CSRF protection, you can safeguard your application from unauthorized actions performed by malicious users.

Configuration

CSRF protection is configured in the config.ini file. The following default settings enable CSRF protection and set the token expiry time:

[SECURITY]
csrf.enabled = true
csrf.expiry = 3600
  • csrf.enabled: Enables or disables CSRF protection.
  • csrf.expiry: Sets the expiry time for the CSRF token in seconds (default is 3600 seconds or 1 hour).

CSRF Token Expiry

The CSRF token has an expiry time configured in the config.ini file. If the token has expired, it will be considered invalid. Ensure your application handles token expiry by prompting the user to refresh the form or session.

Generating CSRF Token

To include a hidden CSRF token input in your forms, use the <csrf/> template directive. This directive generates a hidden input field with the CSRF token, ensuring that each form submission includes a valid token.

Example Usage

<form method="post" action="{{ @ALIASES.login }}">
    <csrf/>
    <!-- other form fields -->
    <input type="submit" value="Submit">
</form>

This example shows how to include a CSRF token in a form. The <csrf/> directive automatically generates and includes the token.

Validating CSRF Token

To validate the CSRF token, use the isCsrfValid() method from the session. This method checks whether the token submitted with the form matches the token stored in the user's session.

Example Usage

if ($this->session->isCsrfValid()) {
    // Token is valid, proceed with form processing
} else {
    // Token is invalid, handle the error
}

This code snippet shows how to validate the CSRF token when processing a form submission. If the token is valid, you can proceed with the form processing. If the token is invalid, handle the error appropriately.

Single CSRF Token Per Session

Like many other frameworks, Sukarix handles a single CSRF token per session. This means that each user's session is associated with one unique CSRF token, which is used to validate all form submissions within that session.

Statera: The Testing Package

Overview

Statera is a testing package designed to work with Sukarix, offering an alternative to PHPUnit. It supports generating coverage reports in formats like Clover, HTML, and Text. Statera operates in both Web and CLI modes, providing flexible testing options.

Key Concepts

TestGroup

A TestGroup is used to group multiple TestScenario instances. It helps organize related test scenarios into logical groups, making it easier to manage and run tests collectively.

TestScenario

A TestScenario represents a specific test case or scenario. It encompasses multiple UnitTest instances that define the individual tests to be run as part of the scenario.

UnitTest

A UnitTest is an individual test case created inside a TestScenario. It contains the actual test logic and assertions to verify the expected behavior of the code under test.

Running Tests

Statera can run tests in both Web and CLI modes, providing detailed coverage reports.

Sukarix Shell Toolbox

Introduction

The Sukarix Shell Toolbox is a versatile utility designed to assist with the configuration, development, monitoring, and administration of Sukarix applications. It is installed by default in the tools directory of the template application when running vagrant up and is currently optimized for Ubuntu 22.04.

Functionality

Configuration

  • --version: Display Sukarix application version.
  • --selfinstall: Make Sukarix runnable from anywhere.

Development

  • --enabletests: Enable running unit tests.
  • --test <-c> : Run unit tests with a test name. Use -c for coverage.
  • --fix: Fix PHP code style.
  • --migrate: Run database migrations.
  • --metrics: Generate code metrics.

Monitoring

  • --check: Check configuration files and processes for problems.

Administration

  • --pull: Pull source code from its repository.
  • --deploy: Deploy the application on a production server.
  • --build-docs: Build the documentation.
  • --jobs: Install the cron jobs.
  • --restart: Restart Sukarix Stack.
  • --stop: Stop Sukarix Stack.
  • --start: Start Sukarix Stack.
  • --clean: Restart and clean all log files.
  • --cleansessions: Clean sessions from the database.
  • --status: Display the running status of components.
  • --zip: Zip up log files for reporting an error.

Example Usage

# Display Sukarix application version
sukarix --version

# Enable running unit tests
sukarix --enabletests

# Run unit tests with a test name and coverage
sukarix --test -c <name>

# Check configuration files and processes for problems
sukarix --check

# Restart Sukarix Stack
sukarix --restart

Testing with Sukarix

The Sukarix Shell Toolbox provides several commands to facilitate testing, ensuring your application maintains high quality and reliability. Here’s how you can leverage these testing commands:

Enabling and Running Tests

Enable Tests

To enable the testing environment, use:

sukarix --enabletests

Running Unit Tests

Run unit tests with an optional coverage report using:

sukarix --test <-c> <name>
  • -c: Generates a coverage report.
  • <name>: Specify the name of the test to run.

Deployment

Introduction

Deploying a Sukarix application involves several steps to ensure your code is properly set up on the production server.

Sukarix Deployment Basics

  1. Upload Your Code:

    • Transfer your application's codebase to the production server using your preferred method (e.g., FTP, SCP, or Git).
  2. Ensure sukarix.sh is in the tools Directory:

    • Make sure the sukarix.sh script is located in the tools directory of your application.
  3. Run the Deployment Script:

    • Execute the deployment script with the -d option:
      ./tools/sukarix.sh -d
      
    • This command performs the following actions:
      • Pulls the latest code from the Git repository.
      • Runs Composer to install dependencies.
      • Applies default permissions to the www-data user.
      • Runs database migrations.
      • Clears the application cache.

Contribution Guide

How to Contribute

We welcome contributions from the community! Here’s how you can help.

  1. Fork the Repository: Create a fork of the Sukarix repository.
  2. Create a Branch: Make a new branch for your feature or bugfix.
  3. Commit Changes: Commit your changes with clear commit messages.
  4. Create a Pull Request: Submit a pull request to the main repository.

Reporting Issues

If you find any bugs or have feature requests, please report them through GitHub Issues.

Community Help

We encourage everyone to contribute to Sukarix and be part of our vibrant community. Whether you have ideas for new features, need support with testing, or want to discuss CLI tools, your input is valuable. Join the conversations and help us improve Sukarix together:

Your contributions make a difference!

Code of Conduct

We strive to maintain a welcoming and inclusive community. Please read our Code of Conduct before contributing.

Thank you for your contributions!

Code of Conduct

Our Pledge

In the interest of fostering an open and welcoming environment, we pledge to make participation in our project and community a harassment-free experience for everyone.

Our Standards

Examples of behavior that contributes to creating a positive environment include:

  • Using welcoming and inclusive language
  • Being respectful of differing viewpoints and experiences
  • Gracefully accepting constructive criticism
  • Focusing on what is best for the community
  • Showing empathy towards other community members

Examples of unacceptable behavior include:

  • The use of inappropriate or unwelcome language or imagery
  • Trolling, insulting/derogatory comments, and personal or political attacks
  • Public or private harassment
  • Publishing others’ private information, such as a physical or electronic address, without explicit permission
  • Other conduct which could reasonably be considered inappropriate in a professional setting

Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.

Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [contact@riadvice.tn]. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.

Attribution

This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html.

Release Notes

Support Policy

Sukarix is currently supported for PHP 8.2+.

Released versions

v0.1.0

🚀 Introduction

  • Version Number: 0.1.0
  • Release Date: 2024-06-14
  • General Overview: First version of the Sukarix Framework.