hryvinskyi / magento2-base
N/A
Installs: 40 254
Dependents: 10
Suggesters: 0
Security: 0
Stars: 5
Watchers: 1
Forks: 3
Open Issues: 0
Type:magento2-module
pkg:composer/hryvinskyi/magento2-base
Requires
- php: >=8.0
- magento/framework: *
README
A comprehensive Magento 2 base module providing:
- Yii2 Framework Helpers: Battle-tested utility classes for array manipulation, HTML generation, JSON handling, and debugging
- ViewModel Registry: Global access to view models in templates without layout XML configuration
- Console Utilities: ANSI terminal control, progress bars, and formatted CLI output
- Layout Debugging: Developer mode tools for layout XML and block structure inspection
Installation Guide
composer require hryvinskyi/magento2-base bin/magento module:enable Hryvinskyi_Base bin/magento setup:upgrade
Table of Contents
Core Features
1. ViewModel Registry ($viewModels
)
Access any view model directly in templates without declaring them in layout XML. The $viewModels
variable is automatically available in all .phtml
templates.
Usage in templates:
<?php /** @var Magento\Framework\View\Element\Template $block */ /** @var Hryvinskyi\Base\Model\ViewModelRegistry $viewModels */ // Get any view model by class name $productViewModel = $viewModels->require(\Vendor\Module\ViewModel\Product::class); $categoryViewModel = $viewModels->require(\Vendor\Module\ViewModel\Category::class); // For ESI blocks with TTL, pass the block reference for proper cache handling $esiViewModel = $viewModels->require(\Vendor\Module\ViewModel\Esi::class, $block); // Use the view model echo $productViewModel->getProductName(); ?>
How it works:
- Automatically injected into all PHP template engines via
di.xml
- Collects cache tags from view models implementing
IdentityInterface
- Properly handles Varnish ESI blocks to prevent incorrect cache purging
- Validates that requested classes implement
ArgumentInterface
Cache handling for ESI blocks:
// Main page - cache tags collected normally $viewModel = $viewModels->require(MyViewModel::class); // ESI block (ttl="300") - pass $block to prevent main page cache pollution $viewModel = $viewModels->require(MyViewModel::class, $block);
2. Layout Debugging (Developer Mode Only)
Automatic layout debugging tools enabled when Magento is in developer mode.
Features:
- Visual block hierarchy display
- Layout XML structure viewer
- Block rendering time tracking
- Cache status indicators
Automatically enabled when:
bin/magento deploy:mode:set developer
Configuration:
The debugging information is controlled by Hryvinskyi\Base\Helper\Config
:
- Only works in developer mode (
State::MODE_DEVELOPER
) - Injected into responses via event observers
- No configuration needed - works out of the box
What you get:
- Block nesting and parent-child relationships
- Template file locations with full paths
- Block class names and cache keys
- Layout handle processing order
- Visual hierarchy with indentation
Yii2 Framework Helper Classes
This module provides proven, battle-tested helper classes from the Yii2 framework, adapted for Magento 2.
ArrayHelper
Comprehensive array manipulation utilities with 30+ methods for working with arrays and objects.
Key Methods:
Method | Description |
---|---|
getValue($array, $key, $default) |
Retrieve nested values using dot notation (user.address.street ) |
setValue(&$array, $key, $value) |
Set nested values using dot notation |
remove(&$array, $key, $default) |
Remove and return array element |
merge($a, $b) |
Recursively merge arrays with smart key handling |
index($array, $key) |
Index/group arrays by specified keys |
getColumn($array, $name) |
Extract column values from multidimensional arrays |
map($array, $from, $to, $group) |
Build key-value maps from arrays |
filter($array, $filters) |
Filter array using dot notation rules |
multisort(&$array, $key, $direction) |
Sort by multiple keys with different directions |
toArray($object, $properties, $recursive) |
Convert objects to arrays with property mapping |
isAssociative($array, $allStrings) |
Check if array is associative |
isIndexed($array, $consecutive) |
Check if array is indexed |
htmlEncode($data, $valuesOnly, $charset) |
Encode HTML entities recursively |
htmlDecode($data, $valuesOnly) |
Decode HTML entities recursively |
keyExists($key, $array, $caseSensitive) |
Check key existence with case options |
isIn($needle, $haystack, $strict) |
Check value membership |
isSubset($needles, $haystack, $strict) |
Check if all values exist |
Advanced Features:
- UnsetArrayValue: Mark array values for removal during merge
- ReplaceArrayValue: Force replacement instead of recursive merge
Usage Examples:
use Hryvinskyi\Base\Helper\ArrayHelper; // Dot notation access $username = ArrayHelper::getValue($_POST, 'user.profile.username', 'guest'); ArrayHelper::setValue($config, 'database.host', 'localhost'); // Array merging with smart handling $merged = ArrayHelper::merge( ['items' => ['apple', 'banana']], ['items' => ['cherry']] ); // Result: ['items' => ['apple', 'banana', 'cherry']] // Indexing and grouping $users = [ ['id' => 1, 'name' => 'John', 'role' => 'admin'], ['id' => 2, 'name' => 'Jane', 'role' => 'user'], ['id' => 3, 'name' => 'Bob', 'role' => 'admin'], ]; $indexed = ArrayHelper::index($users, 'id'); // Result: [1 => [...], 2 => [...], 3 => [...]] $grouped = ArrayHelper::index($users, null, 'role'); // Result: ['admin' => [[...], [...]], 'user' => [[...]]] // Column extraction $ids = ArrayHelper::getColumn($users, 'id'); // Result: [1, 2, 3] // Multi-key sorting ArrayHelper::multisort($users, ['role', 'name'], [SORT_ASC, SORT_DESC]); // Object conversion with custom property mapping $array = ArrayHelper::toArray($object, [ 'id', 'username' => 'name', 'fullName' => function($obj) { return $obj->firstName . ' ' . $obj->lastName; } ]); // Filtering with conditions $filtered = ArrayHelper::filter($users, [ 'id' => [1, 2], // Include only these IDs 'role' => 'admin' // Only admins ]); // Map creation $nameMap = ArrayHelper::map($users, 'id', 'name'); // Result: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] // Force replacement in merge use Hryvinskyi\Base\Helper\ReplaceArrayValue; $merged = ArrayHelper::merge( ['items' => ['a', 'b']], ['items' => new ReplaceArrayValue(['c', 'd'])] ); // Result: ['items' => ['c', 'd']] (replaced, not merged)
Html
HTML generation helper with 40+ methods for programmatic HTML creation and manipulation.
Element Generation:
tag($name, $content, $options)
- Generate any HTML taga($text, $url, $options)
- Hyperlinksmailto($text, $email, $options)
- Email linksimg($src, $options)
- Imageslabel($content, $for, $options)
- Labelsbutton($content, $options)
- ButtonssubmitButton($content, $options)
- Submit buttonsresetButton($content, $options)
- Reset buttons
Form Generation:
beginForm($action, $method, $formKey, $options)
- Form opening with CSRFendForm()
- Form closinginput($type, $name, $value, $options)
- Generic inputtextInput($name, $value, $options)
- Text inputhiddenInput($name, $value, $options)
- Hidden inputpasswordInput($name, $value, $options)
- Password inputfileInput($name, $value, $options)
- File inputtextarea($name, $value, $options)
- Textarearadio($name, $checked, $options)
- Radio buttoncheckbox($name, $checked, $options)
- Checkbox
Lists and Selections:
dropDownList($name, $selection, $items, $options)
- Dropdown selectlistBox($name, $selection, $items, $options)
- Multi-select listcheckboxList($name, $selection, $items, $options)
- Checkbox listradioList($name, $selection, $items, $options)
- Radio button listul($items, $options)
- Unordered listol($items, $options)
- Ordered list
Asset Tags:
cssFile($url, $options)
- CSS link tag with IE conditional supportjsFile($url, $options)
- JavaScript script tag with IE conditional support
CSS/Style Manipulation:
addCssClass(&$options, $class)
- Add CSS class(es)removeCssClass(&$options, $class)
- Remove CSS class(es)addCssStyle(&$options, $style, $overwrite)
- Add inline stylesremoveCssStyle(&$options, $properties)
- Remove inline styles
Utilities:
encode($content, $doubleEncode)
- HTML entity encodingdecode($content)
- HTML entity decodingrenderTagAttributes($attributes)
- Render attribute string with data-* support
Usage Examples:
use Hryvinskyi\Base\Helper\Html; // Generate links echo Html::a('Visit site', 'https://example.com', ['class' => 'external-link', 'target' => '_blank']); echo Html::mailto('Contact us', 'support@example.com'); // Create forms echo Html::beginForm('/checkout/submit', 'post', $formKey, ['id' => 'checkout-form']); echo Html::textInput('email', '', ['class' => 'form-control', 'required' => true]); echo Html::passwordInput('password', '', ['class' => 'form-control']); echo Html::textarea('comments', '', ['rows' => 5, 'class' => 'form-control']); echo Html::submitButton('Submit Order', ['class' => 'btn btn-primary']); echo Html::endForm(); // Dropdowns and lists echo Html::dropDownList('country', 'US', [ 'US' => 'United States', 'CA' => 'Canada', 'UK' => 'United Kingdom' ], ['class' => 'country-select']); // Checkbox/radio lists echo Html::checkboxList('features', ['wifi', 'parking'], [ 'wifi' => 'WiFi', 'parking' => 'Parking', 'pool' => 'Swimming Pool' ]); // Lists echo Html::ul(['Apple', 'Banana', 'Cherry'], [ 'class' => 'fruit-list', 'item' => function($item, $index) { return Html::tag('span', $item, ['data-index' => $index]); } ]); // CSS class manipulation $options = ['class' => 'btn']; Html::addCssClass($options, 'btn-primary btn-lg'); Html::removeCssClass($options, 'btn-lg'); // Result: ['class' => 'btn btn-primary'] // Style manipulation $options = []; Html::addCssStyle($options, 'color: red'); Html::addCssStyle($options, ['font-size' => '14px', 'margin' => '10px']); // Result: ['style' => 'color: red; font-size: 14px; margin: 10px;'] // Asset tags with IE conditional comments echo Html::cssFile('/css/style.css', ['media' => 'screen']); echo Html::cssFile('/css/ie8.css', ['condition' => 'lt IE 9']); echo Html::jsFile('/js/script.js', ['async' => true]); // Custom tags with data attributes echo Html::tag('div', 'Content', [ 'class' => 'container', 'data-module' => 'carousel', 'data-options' => ['autoplay' => true, 'delay' => 3000] ]);
Json
JSON encoding/decoding utilities with enhanced error handling and features beyond native PHP JSON functions.
Features:
- Enhanced error handling with descriptive messages
- Pretty print support via static property
- Object type preservation control
- HTML-safe encoding for embedding in attributes
- Circular reference detection
Methods:
encode($value, $options)
- Encode with error handlinghtmlEncode($value)
- HTML-safe encoding (escapes quotes, tags, amp, apos)decode($json, $asArray)
- Decode with error handling
Properties:
$prettyPrint
- Enable/disable pretty printing (null = use encode options)$keepObjectType
- Avoid objects with zero-indexed keys being encoded as arrays
Usage Examples:
use Hryvinskyi\Base\Helper\Json; // Basic encoding $json = Json::encode(['name' => 'John', 'age' => 30]); // Pretty printing Json::$prettyPrint = true; $prettyJson = Json::encode(['name' => 'John', 'age' => 30]); /* { "name": "John", "age": 30 } */ // HTML-safe encoding for embedding in attributes $safeJson = Json::htmlEncode(['alert' => '<script>alert("xss")</script>']); echo '<div data-config="' . $safeJson . '">'; // Safely embedded // Object type preservation Json::$keepObjectType = true; $json = Json::encode((object)['test']); // Result: {"0":"test"} instead of ["test"] // Decoding with error handling try { $data = Json::decode($jsonString); } catch (\Hryvinskyi\Base\Helper\InvalidParamException $e) { // Handle JSON decode error echo "Invalid JSON: " . $e->getMessage(); } // Decode as object instead of array $object = Json::decode($jsonString, false);
VarDumper
Advanced variable dumping for debugging with syntax highlighting and circular reference handling.
Features:
- Enhanced var_dump with better formatting
- Handles circular references safely
- Configurable depth limits
- Syntax highlighting support
- Export variables as valid PHP code
- Support for complex objects and closures
Methods:
dump($var, $depth, $highlight)
- Display variable contentsdumpAsString($var, $depth, $highlight)
- Get dump as stringexport($var)
- Export as executable PHP codeexportClosure($closure)
- Export closure source code
Usage Examples:
use Hryvinskyi\Base\Helper\VarDumper; // Basic dumping VarDumper::dump($complexObject); // With depth limit and syntax highlighting VarDumper::dump($deeplyNestedArray, 10, true); // Get dump as string for logging $debugInfo = VarDumper::dumpAsString($data, 5); $logger->debug($debugInfo); // Export as PHP code $code = VarDumper::export(['name' => 'John', 'items' => [1, 2, 3]]); // Result: "['name' => 'John', 'items' => [1, 2, 3,],]" // Export complex objects (uses serialize/unserialize) $code = VarDumper::export($product); // Result: "unserialize('...')" // Export closures (extracts source code) $closure = function($x) { return $x * 2; }; $code = VarDumper::export($closure); // Result: "function($x) { return $x * 2; }" // Handle circular references safely $a = ['x' => 1]; $a['self'] = &$a; VarDumper::dump($a); // Safely handles the circular reference
Console Utilities (ConsoleHelper)
Comprehensive ANSI terminal control for CLI commands with 30+ methods for creating rich console applications.
Categories:
- Cursor Control: Move, position, show/hide cursor
- Screen Control: Clear screen, scroll, save/restore positions
- Colors & Formatting: Foreground/background colors, text styles
- Input/Output: Styled output, user input, prompts
- Progress Bars: Visual progress indicators with ETA
- Utilities: Screen size detection, text wrapping, platform detection
Cursor Control
use Hryvinskyi\Base\Helper\ConsoleHelper; ConsoleHelper::moveCursorUp(2); // Move cursor up 2 rows ConsoleHelper::moveCursorDown(1); // Move cursor down 1 row ConsoleHelper::moveCursorForward(5); // Move cursor right 5 columns ConsoleHelper::moveCursorBackward(3); // Move cursor left 3 columns ConsoleHelper::moveCursorNextLine(2); // Move to beginning of 2nd line down ConsoleHelper::moveCursorPrevLine(1); // Move to beginning of 1 line up ConsoleHelper::moveCursorTo(10, 5); // Move to column 10, row 5 ConsoleHelper::saveCursorPosition(); // Save current position ConsoleHelper::restoreCursorPosition(); // Restore saved position ConsoleHelper::hideCursor(); // Hide cursor ConsoleHelper::showCursor(); // Show cursor
Screen Control
ConsoleHelper::clearScreen(); // Clear entire screen ConsoleHelper::clearScreenBeforeCursor(); // Clear from cursor to top ConsoleHelper::clearScreenAfterCursor(); // Clear from cursor to bottom ConsoleHelper::clearLine(); // Clear current line ConsoleHelper::clearLineBeforeCursor(); // Clear line before cursor ConsoleHelper::clearLineAfterCursor(); // Clear line after cursor ConsoleHelper::scrollUp(3); // Scroll up 3 lines ConsoleHelper::scrollDown(2); // Scroll down 2 lines
Colors & Formatting
Color Constants:
// Foreground colors ConsoleHelper::FG_BLACK, FG_RED, FG_GREEN, FG_YELLOW ConsoleHelper::FG_BLUE, FG_PURPLE, FG_CYAN, FG_GREY // Background colors ConsoleHelper::BG_BLACK, BG_RED, BG_GREEN, BG_YELLOW ConsoleHelper::BG_BLUE, BG_PURPLE, BG_CYAN, BG_GREY // Text styles ConsoleHelper::BOLD, ITALIC, UNDERLINE, BLINK ConsoleHelper::NEGATIVE, CONCEALED, CROSSED_OUT ConsoleHelper::FRAMED, ENCIRCLED, OVERLINED
Usage:
// Apply formatting ConsoleHelper::beginAnsiFormat([ConsoleHelper::FG_RED, ConsoleHelper::BOLD]); echo "Error message"; ConsoleHelper::endAnsiFormat(); // Format string $formatted = ConsoleHelper::ansiFormat('Warning', [ConsoleHelper::FG_YELLOW, ConsoleHelper::BOLD]); // xterm 256 colors $fgColor = ConsoleHelper::xtermFgColor(208); // Orange $bgColor = ConsoleHelper::xtermBgColor(235); // Dark gray echo ConsoleHelper::ansiFormat('Text', [$fgColor, $bgColor]); // Color codes in strings (irssi-style) $text = ConsoleHelper::renderColoredString('%R[ERROR]%n %yWarning message', true); // %R = red bold, %n = reset, %y = yellow // Convert ANSI to HTML $html = ConsoleHelper::ansiToHtml($ansiString); // Strip ANSI codes $plain = ConsoleHelper::stripAnsiFormat($ansiString); $length = ConsoleHelper::ansiStrlen($ansiString); // Length without codes
Input/Output
// Output ConsoleHelper::stdout("Message"); // Print to STDOUT ConsoleHelper::stderr("Error"); // Print to STDERR ConsoleHelper::output("Line"); // Print line to STDOUT ConsoleHelper::error("Error"); // Print line to STDERR // Input $input = ConsoleHelper::stdin(); // Read from STDIN $input = ConsoleHelper::input("Name: "); // Prompt and read // Prompt with validation $email = ConsoleHelper::prompt("Email: ", [ 'required' => true, 'pattern' => '/^[^@]+@[^@]+$/', 'error' => 'Invalid email format' ]); $age = ConsoleHelper::prompt("Age: ", [ 'default' => 18, 'validator' => function($input, &$error) { if ($input < 18) { $error = "Must be 18 or older"; return false; } return true; } ]); // Confirmation if (ConsoleHelper::confirm("Delete all files?", false)) { // User confirmed } // Selection menu $choice = ConsoleHelper::select("Choose action:", [ 'c' => 'Create', 'r' => 'Read', 'u' => 'Update', 'd' => 'Delete' ]);
Progress Bars
// Simple progress bar ConsoleHelper::startProgress(0, 1000); for ($i = 1; $i <= 1000; $i++) { usleep(1000); ConsoleHelper::updateProgress($i, 1000); } ConsoleHelper::endProgress(); // With prefix ConsoleHelper::startProgress(0, 100, 'Processing: '); // ... update progress ... ConsoleHelper::endProgress("Done!\n"); // Git-style (status only, no bar) ConsoleHelper::startProgress(0, 1000, 'Counting objects: ', false); // ... update progress ... ConsoleHelper::endProgress("done.\n"); // Custom width ConsoleHelper::startProgress(0, 100, '', 0.5); // 50% of screen width ConsoleHelper::startProgress(0, 100, '', 80); // 80 characters wide
Utilities
// Platform detection if (ConsoleHelper::isRunningOnWindows()) { // Windows-specific code } // ANSI support detection if (ConsoleHelper::streamSupportsAnsiColors(STDOUT)) { // Use colored output } // Screen size list($width, $height) = ConsoleHelper::getScreenSize(); list($width, $height) = ConsoleHelper::getScreenSize(true); // Force refresh // Text wrapping with indentation $wrapped = ConsoleHelper::wrapText($longText, 4); /* Lorem ipsum dolor sit amet. */ // Escape color codes $escaped = ConsoleHelper::escape("String with %y color codes");
Complete CLI Example
use Hryvinskyi\Base\Helper\ConsoleHelper; class MyCommand extends \Symfony\Component\Console\Command\Command { protected function execute($input, $output) { // Header ConsoleHelper::output(ConsoleHelper::ansiFormat('=== Deployment Script ===', [ ConsoleHelper::FG_GREEN, ConsoleHelper::BOLD ])); // Confirmation if (!ConsoleHelper::confirm("Deploy to production?", false)) { ConsoleHelper::output(ConsoleHelper::ansiFormat('Cancelled', [ConsoleHelper::FG_YELLOW])); return 0; } // Progress $tasks = ['compile', 'test', 'deploy', 'cleanup']; ConsoleHelper::startProgress(0, count($tasks), 'Progress: '); foreach ($tasks as $i => $task) { sleep(1); ConsoleHelper::updateProgress($i + 1, count($tasks)); } ConsoleHelper::endProgress(ConsoleHelper::ansiFormat('✓ Completed!', [ ConsoleHelper::FG_GREEN ]) . "\n"); return 0; } }
Requirements
- PHP >= 8.0
- Magento 2.x (2.4+ recommended)
License
This module contains code from two sources with dual licensing:
Yii2 Framework Helpers (BSD-3-Clause License)
The helper classes (ArrayHelper
, Html
, Json
, VarDumper
, ConsoleHelper
) are derived from the Yii2 Framework and are licensed under the BSD-3-Clause License.
- Copyright: © 2008 Yii Software LLC
- License: BSD-3-Clause
- License File: See LICENSE-YII for the full license text
- Original Source: https://github.com/yiisoft/yii2
Magento 2 Modifications (MIT License)
Modifications, adaptations for Magento 2 compatibility, and original features (ViewModelRegistry
, ViewModelCacheTags
, layout debugging, etc.) are licensed under the MIT License.
- Copyright: © 2019-2024 Volodymyr Hryvinskyi
- License: MIT
- License File: See LICENSE for the full license text
Usage Rights
You are free to use, modify, and distribute this module under the terms of both licenses. The BSD-3-Clause license applies to the Yii2-derived code, and the MIT license applies to the Magento 2 adaptations and original features.