Pramnos Console Commands Guide¶
Overview¶
The Pramnos Framework includes a powerful console command system built on Symfony Console components. The console system provides code generation, maintenance tools, and administrative utilities to streamline development workflows.
Available Commands¶
Code Generation Commands¶
The framework provides comprehensive code generation through the create command:
# Create a new model
php bin/pramnos create model User
# Create a controller
php bin/pramnos create controller UserController
# Create a view
php bin/pramnos create view User
# Create complete CRUD system (model + controller + view)
php bin/pramnos create crud User
# Create API endpoint
php bin/pramnos create api UserAPI
# Create database migration
php bin/pramnos create migration CreateUsersTable
Server Commands¶
# Start development server
php bin/pramnos serve
# Start server on specific port
php bin/pramnos serve --port=8080
Maintenance Commands¶
# Migrate log files to structured format
php bin/pramnos migratelogs /path/to/logs --all
# Migrate specific log file
php bin/pramnos migratelogs /path/to/file.log
# Migrate without creating backup
php bin/pramnos migratelogs /path/to/file.log --no-backup
Model Generation¶
Basic Model Creation¶
This generates a model class with: - Database table mapping - Primary key configuration - Basic CRUD methods - Type-safe property declarations - API list method with pagination
Generated Model Structure¶
<?php
namespace MyApp\Models;
/**
* User Model
* Auto generated at: 25/12/2024 10:30
*/
class User extends \Pramnos\Application\Model
{
/**
* User ID
* @var int
*/
public $userid;
/**
* Username
* @var string
*/
public $username;
/**
* Email address
* @var string
*/
public $email;
/**
* Primary key in database
* @var string
*/
protected $_primaryKey = "userid";
/**
* Database table
* @var string
*/
protected $_dbtable = "users";
/**
* Load from database
* @param int $userid ID to load
* @param string $key Primary key on database
* @param boolean $debug Show debug information
* @return $this
*/
public function load($userid, $key = NULL, $debug = false)
{
return parent::_load($userid, null, $key, $debug);
}
/**
* Save to database
* @param boolean $autoGetValues If true, get all values from $_REQUEST
* @param boolean $debug Show debug information (and die)
* @return $this
*/
public function save($autoGetValues = false, $debug = false)
{
return parent::_save(null, null, $autoGetValues, $debug);
}
/**
* Delete from database
* @param integer $userid ID to delete
* @return $this
*/
public function delete($userid)
{
return parent::_delete($userid, null, null);
}
/**
* Get an API-formatted list with pagination, field selection, and search capabilities
*/
public function getApiList($fields = array(), $search = '',
$order = '', $page = 0, $itemsPerPage = 10,
$debug = false, $returnAsModels = false, $useGetData = true)
{
return parent::_getApiList(
$fields, $search, $order, '', '', '',
null, null, $page, $itemsPerPage, $debug, $returnAsModels, $useGetData
);
}
}
Model Generation Options¶
# Generate model for specific table
php bin/pramnos create model User --table=custom_users
# Generate model with schema specification (PostgreSQL)
php bin/pramnos create model User --schema=public
Model Registry¶
Generated models are automatically registered in app/model-registry.json:
[
{
"className": "User",
"namespace": "MyApp\\Models",
"fullClassName": "MyApp\\Models\\User",
"table": "users",
"schema": "",
"createdAt": "2024-12-25T10:30:00+00:00",
"updatedAt": "2024-12-25T10:30:00+00:00"
}
]
Controller Generation¶
Basic Controller Creation¶
CRUD Controller Generation¶
This generates a complete CRUD controller with: - Display action (list view) - Show action (detail view) - Edit action (create/update form) - Save action (form processing) - Delete action (record removal) - JSON data method for datatables
Generated Controller Structure¶
<?php
namespace MyApp\Controllers;
/**
* User Controller
* Auto generated at: 25/12/2024 10:30
*/
class User extends \Pramnos\Application\Controller
{
/**
* User controller constructor
* @param Application $application
*/
public function __construct(?\Pramnos\Application\Application $application = null)
{
$this->addAuthAction(
array('edit', 'save', 'delete', 'show', 'getUser')
);
parent::__construct($application);
}
/**
* Display a listing of the resource
* @return string
*/
public function display()
{
$view = $this->getView('user');
$model = new \MyApp\Models\User($this);
$view->items = $model->getList();
$this->application->addbreadcrumb('User', sURL . 'User');
$doc = \Pramnos\Framework\Factory::getDocument();
$doc->title = 'User';
return $view->display();
}
/**
* Display the specified resource
* @return string
*/
public function show()
{
$view = $this->getView('user');
$model = new \MyApp\Models\User($this);
$request = new \Pramnos\Http\Request();
$model->load($request->getOption());
$view->addModel($model);
$this->application->addbreadcrumb('User', sURL . 'User');
$this->application->addbreadcrumb('View ' . $model->userid, sURL . 'User/show/' . $model->userid);
$doc = \Pramnos\Framework\Factory::getDocument();
$doc->title = $model->userid . ' | User';
return $view->display('show');
}
/**
* Show the form for creating a new resource or editing an existing one
* @return string
*/
public function edit()
{
$view = $this->getView('user');
$model = new \MyApp\Models\User($this);
$request = new \Pramnos\Http\Request();
$model->load($request->getOption());
$view->addModel($model);
$this->application->addbreadcrumb('User', sURL . 'User');
if ($model->userid > 0) {
$this->application->addbreadcrumb('View ' . $model->userid, sURL . 'User/show/' . $model->userid);
$this->application->addbreadcrumb('Edit', sURL . 'User/edit/' . $model->userid);
} else {
$this->application->addbreadcrumb('Create', sURL . 'User/edit/0');
}
$doc = \Pramnos\Framework\Factory::getDocument();
$doc->title = ($model->userid > 0 ? 'Edit' : 'Create') . ' | User';
return $view->display('edit');
}
/**
* Store a newly created or edited resource in storage.
*/
public function save()
{
$model = new \MyApp\Models\User($this);
$request = new \Pramnos\Http\Request();
$model->load($request->getOption());
// Auto-generated field assignments based on database schema
$model->username = trim(strip_tags($request->get('username', '', 'post')));
$model->email = trim(strip_tags($request->get('email', '', 'post')));
$model->firstname = trim(strip_tags($request->get('firstname', '', 'post')));
$model->save();
$this->redirect(sURL . 'User');
}
/**
* Remove the specified resource from storage
*/
public function delete()
{
$model = new \MyApp\Models\User($this);
$request = new \Pramnos\Http\Request();
$model->delete($request->getOption());
$this->redirect(sURL . 'User');
}
/**
* Returns the resource in JSON format
* @return string
*/
public function getUser()
{
$model = new \MyApp\Models\User($this);
\Pramnos\Framework\Factory::getDocument('json');
return $model->getJsonList();
}
}
View Generation¶
Basic View Creation¶
Full CRUD Views¶
This generates complete view templates:
- index.html.php - List view with datatables
- edit.html.php - Create/edit form
- show.html.php - Detail view
Generated View Examples¶
List View (index.html.php)¶
<div class="card">
<div class="card-header">
<h1 class="page-head-line">User list</h1>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<a href="<?php echo sURL; ?>User/edit/0">
<button type="button" class="btn btn-primary">
<i class="fa fa-plus"></i> <?php l('New'); ?>
</button>
</a>
</div>
<br /><br />
</div>
<?php
$datatable = new \Pramnos\Html\Datatable('user', URL . 'User/getUser');
// Auto-generated columns based on database schema
$datatable->addColumn('Username', true, true, true, '', '', true, 'left', true);
$datatable->addColumn('Email', true, true, true, '', '', true, 'left', true);
$datatable->addColumn('First Name', true, true, true, '', '', true, 'left', true);
$datatable->addColumn('Actions');
$datatable->jui = false;
$datatable->bootstrap = true;
echo $datatable->render();
?>
</div>
</div>
Edit Form (edit.html.php)¶
<div class="card">
<div class="card-body">
<form action="[sURL]User/save/<?php echo $this->model->userid; ?>" method="post" role="form">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" value="<?php echo $this->model->username; ?>"
id="username" name="username" class="form-control">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" value="<?php echo $this->model->email; ?>"
id="email" name="email" class="form-control">
</div>
<div class="form-group">
<label for="firstname">First Name:</label>
<input type="text" value="<?php echo $this->model->firstname; ?>"
id="firstname" name="firstname" class="form-control">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary"><?php l('Save'); ?></button>
</div>
</form>
</div>
</div>
API Generation¶
Creating API Endpoints¶
This generates a complete REST API controller with: - GET endpoints for listing and individual records - POST endpoints for creating records - PUT endpoints for updating records - DELETE endpoints for removing records - Automatic API documentation (PHPDoc format)
Generated API Controller¶
<?php
namespace MyApp\Api\Controllers;
/**
* UserAPI Controller
* Auto generated at: 25/12/2024 10:30
*/
class UserAPI extends \Pramnos\Application\Controller
{
/**
* @api {get} 1.0/user List
* @apiVersion 1.0.0
* @apiGroup User
* @apiName listUser
* @apiDescription List of User objects with pagination, search, sorting and field selection
*
* @apiHeader {String} apiKey Application unique api key
* @apiHeader {String} accessToken Authenticated user access token
*
* @apiParam {Number} [page=0] Page number for pagination. Set to 0 to get all results
* @apiParam {Number} [limit=20] Limit number of results per page
* @apiParam {String} [sort] Sort by field. Syntax: [+-]fieldname,[+-]fieldname
* @apiParam {String} [search] Global search term or JSON object for field-specific search
* @apiParam {String} [fields] Specify which fields to return (comma-separated or JSON array)
*/
public function display()
{
if (!isset($_SESSION['user']) || !is_object($_SESSION['user'])) {
return array('status' => 401);
}
$user = $_SESSION['user'];
if ($user->userid < 2) {
return array('status' => 401);
}
$model = new \MyApp\Models\User($this);
// Get parameters from request
$fields = \Pramnos\Http\Request::staticGet('fields', array(), 'get');
$search = \Pramnos\Http\Request::staticGet('search', '', 'get');
$sort = \Pramnos\Http\Request::staticGet('sort', '', 'get');
$page = (int) \Pramnos\Http\Request::staticGet('page', 0, 'get', 'int');
$limit = (int) \Pramnos\Http\Request::staticGet('limit', 20, 'get', 'int');
// Use the new getApiList method for enhanced pagination, search, and field selection
return $model->getApiList(
$fields,
$search,
$sort,
$page,
$limit,
false, // debug
false, // returnAsModels
false // useGetData
);
}
/**
* @api {get} 1.0/user/:userid Read
* @apiVersion 1.0.0
* @apiGroup User
* @apiName readUser
* @apiDescription Read a specific User object
*
* @apiHeader {String} apiKey Application unique api key
* @apiHeader {String} accessToken Authenticated user access token
* @apiParam {Number} userid Id to load
*/
public function readUser($userid)
{
if (!isset($_SESSION['user']) || !is_object($_SESSION['user'])) {
return array('status' => 401);
}
$user = $_SESSION['user'];
if ($user->userid < 2) {
return array('status' => 401);
}
$model = new \MyApp\Models\User($this);
$model->load((int) $userid);
if ($model->userid == 0) {
return array('status' => 404);
}
$data = $model->getData();
return array('data' => $data);
}
/**
* @api {post} 1.0/user Create
* @apiVersion 1.0.0
* @apiGroup User
* @apiName createUser
* @apiDescription Create a User
*
* @apiHeader {String} apiKey Application unique api key
* @apiHeader {String} accessToken Authenticated user access token
*
* @apiBody {String} username Username
* @apiBody {String} email Email address
* @apiBody {String} [firstname] First name
*/
public function createUser()
{
if (!isset($_SESSION['user']) || !is_object($_SESSION['user'])) {
return array('status' => 401);
}
$user = $_SESSION['user'];
$model = new \MyApp\Models\User($this);
$model->username = trim(strip_tags(\Pramnos\Http\Request::staticGet('username', '', 'post')));
$model->email = trim(strip_tags(\Pramnos\Http\Request::staticGet('email', '', 'post')));
$model->firstname = trim(strip_tags(\Pramnos\Http\Request::staticGet('firstname', '', 'post')));
$model->save();
return array(
'status' => 201,
'data' => $model->getData()
);
}
/**
* @api {put} 1.0/user/:userid Update
* @apiVersion 1.0.0
* @apiGroup User
* @apiName updateUser
* @apiDescription Update a specific User object
*
* @apiHeader {String} apiKey Application unique api key
* @apiHeader {String} accessToken Authenticated user access token
* @apiParam {Number} userid Id to update
*/
public function updateUser($userid)
{
if (!isset($_SESSION['user']) || !is_object($_SESSION['user'])) {
return array('status' => 401);
}
$user = $_SESSION['user'];
$model = new \MyApp\Models\User($this);
$model->load((int) $userid);
if ($model->userid == 0) {
return array('status' => 404);
}
$model->username = trim(strip_tags(\Pramnos\Http\Request::staticGet('username', $model->username, 'put')));
$model->email = trim(strip_tags(\Pramnos\Http\Request::staticGet('email', $model->email, 'put')));
$model->firstname = trim(strip_tags(\Pramnos\Http\Request::staticGet('firstname', $model->firstname, 'put')));
$model->save();
return array(
'status' => 202,
'data' => $model->getData()
);
}
/**
* @api {delete} 1.0/user/:userid Delete
* @apiVersion 1.0.0
* @apiGroup User
* @apiName deleteUser
* @apiDescription Delete a User
*
* @apiHeader {String} apiKey Application unique api key
* @apiHeader {String} accessToken Authenticated user access token
* @apiParam {Number} userid Id to delete
*/
public function deleteUser($userid)
{
$model = new \MyApp\Models\User($this);
$model->load((int) $userid);
if ($model->userid == 0) {
return array('status' => 404);
}
$model->delete($userid);
return array('status' => 202);
}
}
API Route Registration¶
API routes are automatically added to src/Api/routes.php:
$router->delete(
'/user/{userid}',
function ($userid) {
$controller = $this->getController('UserAPI');
return $controller->deleteUser($userid);
}
);
$router->put(
'/user/{userid}',
function ($userid) {
$controller = $this->getController('UserAPI');
return $controller->updateUser($userid);
}
);
$router->get(
'/user/{userid}',
function ($userid) {
$controller = $this->getController('UserAPI');
return $controller->readUser($userid);
}
);
$router->get(
'/user',
function () {
$controller = $this->getController('UserAPI');
return $controller->display();
}
);
$router->post(
'/user',
function () {
$controller = $this->getController('UserAPI');
return $controller->createUser();
}
);
CRUD Generation¶
Complete CRUD System¶
This single command creates: 1. Model with database mapping 2. Controller with full CRUD operations 3. Views for list, create, edit, and detail pages
The output shows the status of each component:
Migration System¶
Creating Migrations¶
This generates a migration class:
<?php
namespace MyApp\Migrations;
/**
* CreateUsersTable migration
* Auto generated at: 25/12/2024 10:30
*/
final class MigrationCreateUsersTable extends \Pramnos\Database\Migration
{
/**
* Version that this migration sets
* @var string
*/
public $version = 'CreateUsersTable';
/**
* Description of the migration
* @var string
*/
public $description = '';
/**
* Should the migration executed automatically
* @var bool
*/
public $autoExecute = true;
/**
* Run the migration
* @return void
*/
public function up() : void
{
// this up() migration is auto-generated, please modify it to your needs
}
/**
* Undo the migration
* @return void
*/
public function down() : void
{
// this down() migration is auto-generated, please modify it to your needs
}
}
Migration Registry¶
Migrations are automatically registered in app/migrations.php:
<?php
return [
/*
|--------------------------------------------------------------------------
| Migrations List
|--------------------------------------------------------------------------
|
| These migrations will be executed in order on application execution
|
*/
'CreateUsersTable' => 'MigrationCreateUsersTable'
];
Development Server¶
Starting the Server¶
# Start on default port (8000)
php bin/pramnos serve
# Start on custom port
php bin/pramnos serve --port=8080
# Start with custom host
php bin/pramnos serve --host=0.0.0.0 --port=8080
The development server provides: - Hot reloading for PHP files - Automatic routing - Error display - Access to framework features
Log Migration¶
Migrating Log Files¶
The framework includes a powerful log migration system to convert legacy log formats to structured JSON:
# Migrate all .log files in a directory
php bin/pramnos migratelogs /path/to/logs --all
# Migrate specific file
php bin/pramnos migratelogs /path/to/application.log
# Migrate without backup
php bin/pramnos migratelogs /path/to/application.log --no-backup
Migration Features¶
- Preserves timestamps - Extracts timestamps from various log formats
- Handles multiline logs - Properly processes stack traces and error messages
- Creates backups - Original files are backed up with
.bakextension - Progress tracking - Shows progress bar for large files
- Error handling - Continues processing if individual lines fail
Example Migration Output¶
Processing: application.log
1000/1000 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
Migration completed successfully:
Files processed: 1 (Failed: 0)
Lines processed: 1000 (Converted: 987)
Duration: 0.45 seconds
Advanced Features¶
Foreign Key Detection¶
The code generator automatically detects foreign key relationships and generates appropriate model methods:
// If a 'user_id' field is detected, this method is auto-generated
public function getUser()
{
if ($this->user_id > 0) {
$user = new \MyApp\Models\User($this);
$user->load($this->user_id);
return $user;
}
return null;
}
Data Type Handling¶
The generator creates type-safe field assignments based on database schema:
// Integer fields
$model->count = \Pramnos\Http\Request::staticGet('count', 0, 'post', 'int');
// Boolean fields
$tmpVar = \Pramnos\Http\Request::staticGet('active', '', 'post');
if ($tmpVar == 'true' || $tmpVar == 'on' || $tmpVar == "yes" || $tmpVar === '1' || $tmpVar === 1) {
$tmpVar = true;
} else {
$tmpVar = false;
}
$model->active = $tmpVar;
// Float fields
$model->price = (float) \Pramnos\Http\Request::staticGet('price', '', 'post');
// String fields (with sanitization)
$model->name = trim(strip_tags(\Pramnos\Http\Request::staticGet('name', '', 'post')));
API Documentation Generation¶
Generated API controllers include comprehensive PHPDoc annotations compatible with API documentation tools:
/**
* @api {get} 1.0/user List
* @apiVersion 1.0.0
* @apiGroup User
* @apiName listUser
* @apiDescription List of User objects with pagination, search, sorting and field selection
*
* @apiHeader {String} apiKey Application unique api key
* @apiHeader {String} accessToken Authenticated user access token
*
* @apiParam {Number} [page=0] Page number for pagination
* @apiParam {Number} [limit=20] Limit number of results per page
* @apiParam {String} [sort] Sort by field. Syntax: [+-]fieldname,[+-]fieldname
* @apiParam {String} [search] Global search term or JSON field-specific search
* @apiParam {String} [fields] Comma-separated or JSON array of fields to return
*
* @apiSuccess {Array} data List of User objects
* @apiSuccess {Object} [pagination] Pagination information (only when page > 0)
* @apiSuccess {Number} pagination.currentpage Current page number
* @apiSuccess {Number} pagination.itemsperpage Items per page
* @apiSuccess {Number} pagination.totalitems Total number of items
* @apiSuccess {Number} pagination.totalpages Total number of pages
* @apiSuccess {Boolean} pagination.hasnext Whether there is a next page
* @apiSuccess {Boolean} pagination.hasprevious Whether there is a previous page
* @apiSuccess {Array} fields List of fields included in the response
*/
Configuration¶
Console Application Setup¶
The console application is configured in src/Pramnos/Console/Application.php:
protected function registerCommands()
{
$this->add(new \Pramnos\Console\Commands\Create());
$this->add(new \Pramnos\Console\Commands\Serve());
$this->add(new \Pramnos\Console\Commands\MigrateLogs());
// Add custom commands here
// $this->add(new \MyApp\Console\CustomCommand());
}
Custom Command Creation¶
You can create custom console commands by extending Symfony's Command class:
<?php
namespace MyApp\Console;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
class CustomCommand extends Command
{
protected function configure()
{
$this->setName('custom:task');
$this->setDescription('Execute custom task');
$this->setHelp('This command performs a custom task');
$this->addArgument('parameter', InputArgument::REQUIRED, 'Required parameter');
$this->addOption('option', 'o', InputOption::VALUE_OPTIONAL, 'Optional parameter');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$parameter = $input->getArgument('parameter');
$option = $input->getOption('option');
$output->writeln("Executing custom task with parameter: $parameter");
// Your custom logic here
return Command::SUCCESS;
}
}
Best Practices¶
Model Generation¶
- Use descriptive table names - The generator uses table names to create class names
- Define proper primary keys - Ensure your tables have clear primary key definitions
- Add column comments - Database column comments become PHPDoc annotations
- Use consistent naming - Follow your project's naming conventions
Controller Generation¶
- Plan your actions - Consider which actions need authentication
- Use meaningful names - Controller names should reflect their purpose
- Review generated code - Always review and customize generated controllers
- Add validation - Implement proper input validation in save methods
API Development¶
- Design RESTful endpoints - Follow REST conventions for API design
- Implement proper authentication - Use JWT or session-based auth
- Add input validation - Validate all API inputs
- Handle errors gracefully - Return appropriate HTTP status codes
- Document your APIs - Maintain the generated API documentation
Database Migrations¶
- Make migrations idempotent - Migrations should be safe to run multiple times
- Use descriptive names - Migration names should describe what they do
- Test migrations - Always test migrations on development data first
- Keep migrations small - Break large changes into smaller migrations
Development Workflow¶
- Start with models - Generate models first to establish data structure
- Create controllers - Build controllers with required business logic
- Design views - Create user-friendly interfaces
- Build APIs - Add API endpoints for mobile/frontend integration
- Write tests - Create tests for critical functionality
Troubleshooting¶
Common Issues¶
Database Connection Errors
# Ensure database configuration is correct in your app settings
# Check database credentials and connection
Permission Errors
# Ensure the web server has write permissions to:
# - app/ directory (for registry files)
# - includes/ directory (for generated files)
# - logs/ directory (for logging)
chmod -R 755 app/ includes/ logs/
Generated Code Issues - Review generated code for customization needs - Check namespace configuration in application settings - Verify database table structure matches expectations
Console Command Not Found
- Ensure bin/pramnos has execute permissions
- Check PHP CLI is available and working
- Verify Composer dependencies are installed
The Pramnos console system provides a comprehensive set of tools for rapid application development, making it easy to scaffold complete applications with minimal manual coding while maintaining code quality and consistency.
CommandBase¶
Pramnos\Console\CommandBase — abstract base class for lock-guarded and interactive console commands. All long-running or daemon-style commands should extend this instead of Command directly.
abstract class CommandBase extends \Symfony\Component\Console\Command\Command
{
abstract protected function getJobName(): string;
}
Lock-file job guards¶
class MyDaemon extends \Pramnos\Console\CommandBase
{
protected function getJobName(): string { return 'my_daemon'; }
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (!$this->beginJob($output)) {
$output->writeln('<error>Already running.</error>');
return Command::FAILURE;
}
while (true) {
$this->heartbeat(); // touch lock file so orchestrator knows we're alive
// ... do work ...
}
$this->endJob();
return Command::SUCCESS;
}
}
| Method | Description |
|---|---|
beginJob(OutputInterface, bool $registerShutdown=true): bool |
Returns false if already running; creates lock file + SIGINT handler |
endJob(): void |
Removes the lock file (also called by shutdown/signal handlers) |
heartbeat(): void |
touch() the lock file to signal liveness |
checkIfRunning(): bool |
Checks lock file + PID liveness; treats stale locks (>2 h) as gone |
Terminal control¶
| Method | Description |
|---|---|
clearScreen(OutputInterface) |
Clear terminal |
hideCursor(OutputInterface) |
Hide cursor during live dashboard |
showCursor(OutputInterface) |
Restore cursor |
detectTerminalSize(): array{int,int} |
Returns [height, width] via stty size |
Progress bar¶
$output->write("\r" . $this->buildProgressBar($current, $total));
// → " [████████████..........] 60 of 100 (60%)"
Text utilities¶
| Method | Description |
|---|---|
formatBytes(int|float, int $precision=2): string |
1024 → "1 KB", 1048576 → "1 MB" |
formatTime(int $seconds): string |
3723 → "01:02:03" (HH:MM:SS) |
visibleLength(string): int |
Character count ignoring ANSI escape sequences |
truncateText(string, int $maxLen): string |
Adds ... if visible length exceeds maxLen |
Dashboard rendering¶
Used to build live bordered terminal dashboards:
┌──────────────────────────────────────┐
│ QUEUE PROCESSOR v2 │
├──────────────────────────────────────┤
│ Time: 2026-05-05 14:30:00 │ Uptime: 00:12:34 │ CPU: 2.1 │ Memory: 48 MB │
├──────────────────────────────────────┤
│ Mode: Normal │ State: Running │ Tasks today: 1024 │
└──────────────────────────────────────┘
| Method | Description |
|---|---|
buildDashboardHeader(string $title, int $borderLen): string |
Top border with centered title |
buildDashboardSectionSeparator(int $borderLen): string |
Section divider ├──┤ |
buildDashboardFooter(int $borderLen): string |
Bottom border └──┘ |
padDashboardLine(string $content, int $borderLen): string |
Pad content with side borders │ … │ |
buildDashboardRows(string[] $segments, int $borderLen): string |
Fit segments side-by-side with │ separator |
buildSystemStatusSegments(int $startTime, float $cpu, int|float $mem): string[] |
['Time: …', 'Uptime: …', 'CPU: …', 'Memory: …'] |
renderDashboardFrame(OutputInterface, string $title, string[] $systemSegments, string[] $sections, int $terminalWidth): void |
Full frame render (cursor-home → write → erase-below) |
renderDashboardFrameAutoSystem(OutputInterface, string $title, string[] $sections, int $terminalWidth): void |
As above with auto-built system segments |
Migrating Urbanwater commands¶
// Before (Urbanwater-local):
use Urbanwater\ConsoleCommands\CommandBase;
// After (framework-level — no code changes in the command):
use Pramnos\Console\CommandBase;
DaemonOrchestrator¶
Pramnos\Console\DaemonOrchestrator — abstract generic process supervisor that reconciles desired-vs-actual daemon state. Handles crash detection, heartbeat monitoring, git-hash restart on deploy, pre-spawn dedup, graceful stop, and a live interactive dashboard.
Extending¶
Override three abstract methods and optionally hook lifecycle checks:
use Pramnos\Console\DaemonOrchestrator;
class MyOrchestrator extends DaemonOrchestrator
{
protected function getJobName(): string { return 'my_orchestrator'; }
protected function getEntryPoint(): string { return ROOT . '/bin/myapp'; }
protected function getDashboardTitle(): string { return ' MY APP ORCHESTRATOR '; }
protected function buildDesiredProcesses(): array
{
return [[
'id' => 'queue-1',
'daemon' => 'queue',
'workerId' => 'worker-1',
'lockFile' => ROOT . '/var/QUEUE_WORKER_1',
'tokens' => ['queue:process', '--worker-id', 'worker-1', '--daemon'],
]];
}
// Optional — read from application settings:
protected function isOrchestratorEnabled(): bool
{
return \Pramnos\Application\Settings::getSetting('daemon_enabled', true);
}
}
php bin/myapp daemons:start
php bin/myapp daemons:start --once # single reconcile cycle
php bin/myapp daemons:start --interactive # live terminal dashboard
php bin/myapp daemons:start --dry-run # show planned actions, no changes
php bin/myapp daemons:start --interval=5 # reconcile every 5 seconds
Process definition keys¶
| Key | Required | Description |
|---|---|---|
id |
yes | Unique slot identifier for state tracking |
daemon |
yes | Daemon type label ('queue', 'kafka', etc.) |
workerId |
yes | --worker-id argument value |
lockFile |
yes | Absolute path to the worker's lock file |
tokens |
yes | CLI arguments passed to getEntryPoint() |
requireLockFile |
no | Whether a healthy lock file is required (default true) |
shellCommand |
no | Raw shell command — overrides tokens |
db:seed — Database Seeder Command¶
# Run all seeders in database/seeds/
php bin/pramnos db:seed
# Run a single seeder by class name
php bin/pramnos db:seed UsersSeeder
# Run seeders from a custom directory
php bin/pramnos db:seed --path=/custom/seeds/
Seeders must extend Pramnos\Database\Seeder and implement run():
use Pramnos\Database\Seeder;
class UsersSeeder extends Seeder
{
public function run(): void
{
for ($i = 0; $i < 10; $i++) {
$this->insert('users', [
'name' => 'User ' . $i,
'email' => 'user' . $i . '@example.com',
]);
}
}
}
Default seeds path: ROOT . '/database/seeds/'. Exit codes: 0 = success, 1 = failure.
Interactive Migration Wizard¶
create:migration (called without a name argument) launches an interactive wizard:
The wizard collects the full schema definition — columns, types, nullable/default/unique flags, foreign keys — and writes a migration with a complete up() / down(). After generating the migration it prompts to optionally create a Model, Web Controller, API Controller, and Seeder from the same session.
Migration description: create users table
Table name: #PREFIX#users
Add auto-increment primary key id? [yes]
── Columns ──────────────────────────────────────────────────────────
Column name (Enter to finish): name
Type [string (VARCHAR)]:
Length [255]: 100
Nullable? [no]:
Default value (blank = none, '' = empty string):
Unique? [no]:
Column name (Enter to finish): ← blank = done
Add timestamps (created_at / updated_at)? [yes]
Add another table to this migration? [no]:
✓ Migration created: app/migrations/2026_05_06_120000_create_users_table.php
Run this migration now? [yes]
── Also create ───────────────────────────────────────────────────────
Create Model (Users)? [yes]
Create Web Controller (UsersController)? [yes]
Create API Controller (UsersApiController)? [yes]
Create Seeder (UsersSeeder with fake data)? [yes]
UI-aware controller and view generation¶
The wizard detects the application's UI setup:
| Setup detected | Generated output |
|---|---|
| Bootstrap + DataTables + Select2 | ServerSide DataTable list, Select2 FK dropdowns |
| Bootstrap only | Plain <table class="table"> list |
| Plain CSS | Minimal HTML table, no framework dependencies |
Non-interactive usage (unchanged)¶
Seeder fake-data heuristics¶
| Column name contains | Generated fake value |
|---|---|
email |
'user' . $i . '@example.com' |
name |
'Name ' . $i |
status |
['active','inactive','pending'][$i % 3] |
password |
password_hash('password' . $i, PASSWORD_DEFAULT) |
token |
bin2hex(random_bytes(16)) |
uuid type |
UUID v4 formatted string |
boolean type |
($i % 2 === 0) |
decimal/float type |
round($i * 9.99, 2) |
| fallback | 'value_' . $i |
Auto-managed columns (id, created_at, updated_at, deleted_at) are never included in seed inserts.
Related Documentation¶
- Framework Guide — MVC architecture for generated code
- Migration Guide — Migration system and MigrationRunner
- Database API Guide — Database patterns used in generated models
- Authentication Guide — Implementing authentication in generated controllers
- Routing Guide — Route registration for generated controllers
- Logging System Guide — Log migration tools and monitoring