icebox-php/framework
最新稳定版本:v0.1.2
Composer 安装命令:
composer require icebox-php/framework
包简介
The Icebox Framework.
关键字:
README 文档
README
This repository contains the core code of the Icebox framework.
ActiveRecord Implementation
Icebox includes a modern PDO-based ActiveRecord implementation with Rails-style query builder.
Database Configuration
use Icebox\ActiveRecord\Config as ArConfig; $database_url = (string) env('DATABASE_URL'); if($database_url == null) { throw new \LengthException('DATABASE_URL must have a value. example: mysql://username:password@host:port/database_name'); } // parse the URL $parsed = ArConfig::parseDatabaseUrl($database_url); // Extract components $dsn = $parsed['dsn']; $username = $parsed['username']; $password = $parsed['password']; $options = $parsed['options']; // User can customize options if needed $options[PDO::ATTR_PERSISTENT] = true; // Create PDO connection $connection = new PDO($dsn, $username, $password, $options); // Initialize ActiveRecord ArConfig::initialize($connection);
Creating Models
use Icebox\Model; class User extends Model { // Optional: specify custom table name protected static $table = 'users'; // Optional: specify custom primary key protected static $primaryKey = 'id'; } class Post extends Model { // Table name will be inferred as 'posts' // Primary key will default to 'id' }
Basic CRUD Operations
// Create $user = new User(['name' => 'John', 'email' => 'john@example.com']); $user->save(); // Read by primary key $user = User::find(1); // Update $user = User::find(1); $user->name = 'Jane'; $user->save(); // Or update multiple attributes $user->updateAttributes(['name' => 'Jane', 'email' => 'jane@example.com']); // Delete $user->delete();
Rails-style Query Builder
Icebox uses a Rails-inspired query builder with a single where() method for all queries.
Basic Queries
// Equality (multiple syntaxes) User::where('name', 'John')->get(); User::where(['name' => 'John', 'active' => 1])->get(); // Comparison operators User::where('age', '>', 18)->get(); User::where('age', '>=', 21)->get(); User::where('name', 'LIKE', 'John%')->get(); // NULL checks (Rails-style) User::where('approved_at', null)->get(); // IS NULL User::where('approved_at', '!=', null)->get(); // IS NOT NULL User::whereNull('deleted_at')->get(); User::whereNotNull('approved_at')->get(); // IN clauses User::where('id', [1, 2, 3])->get(); // IN (1,2,3) User::whereIn('category_id', [1, 2, 3])->get(); User::whereNotIn('status', ['banned', 'inactive'])->get(); // BETWEEN User::whereBetween('age', [18, 65])->get(); // OR conditions User::where(['or' => ['status' => 'active', 'status' => 'pending']])->get(); User::where('status', 'active')->orWhere('status', 'pending')->get(); // Raw SQL User::where('price > cost * ?', [1.5])->get(); // Get all records User::where()->get(); User::where([])->get();
Method Chaining
User::where('active', 1) ->where('age', '>', 18) ->orderBy('name', 'DESC') ->limit(10) ->offset(5) ->get();
Aggregates and Checks
// Count records $count = User::where('active', 1)->count(); // Check if exists $exists = User::where('email', 'john@example.com')->exists(); // Get first result $user = User::where('active', 1)->first();
Model Methods Available
find($id)- Find by primary keywhere($column, $operator = null, $value = null)- Query builder entry pointsave()- Create or update recordupdateAttributes($attributes)- Update multiple attributesdelete()- Delete recordtoArray()- Convert to arrayisDirty()- Check if model has changesgetDirty()- Get changed attributes
Query Builder Methods
where($column, $operator = null, $value = null)- Add WHERE conditionorWhere($column, $operator = null, $value = null)- Add OR WHERE conditionwhereNull($column)- WHERE IS NULLwhereNotNull($column)- WHERE IS NOT NULLwhereIn($column, array $values)- WHERE INwhereNotIn($column, array $values)- WHERE NOT INwhereBetween($column, array $values)- WHERE BETWEENorderBy($column, $direction = 'ASC')- ORDER BYlimit($limit)- LIMIToffset($offset)- OFFSETget()- Execute and get resultsfirst()- Get first resultcount()- Get count of recordsexists()- Check if any records exist
Transactions
\Icebox\ActiveRecord\Connection::beginTransaction(); try { $user1->save(); $user2->save(); \Icebox\ActiveRecord\Connection::commit(); } catch (Exception $e) { \Icebox\ActiveRecord\Connection::rollback(); }
Interactive Console
Icebox includes an interactive PHP console (REPL) powered by PsySH, similar to Rails console:
php icebox console
php icebox c # Short alias
This starts an interactive PHP shell. When used within an Icebox application, the framework and application environment will be automatically loaded.
Features
- Tab completion for class names, methods, and variables
- Syntax highlighting for better readability
- Documentation lookup with
doc function_name - Source code viewing with
show function_name - Command history with up/down arrows
- Error handling with pretty output
Example Usage
$ php icebox console Loading development environment (PHP 8.5.0) Type 'exit' to quit, 'help' for help. Psy Shell v0.12.17 (PHP 8.5.0 — cli) by Justin Hileman >>> echo App::root_url(); http://localhost/myapp >>> $user = User::find(1); >>> echo $user->name; John Doe >>> exit
Available Commands in PsySH
exitorquit- Exit the consolehelp- Show helpdoc function_name- Show documentation for a functionshow function_name- Show source code for a functionls- List variables in current scopeclear- Clear the screen
Note for Application Usage
When using the console within an Icebox application, the application bootstrap will handle loading the framework and environment. The console command simply starts PsySH with the development environment.
Logging
Icebox includes a simple, Rails-like logger built on Monolog with PSR-3 compatibility. The logger supports multiple simultaneous handlers and works for both terminal and web applications.
Request Logging
When running the development server (php icebox server), Icebox automatically suppresses the default PHP built‑in server logs and provides Rails‑style request logging:
PHP server logs suppressed. Application logs will appear below.
2025-12-22T21:46:56.957795+00:00 icebox - INFO - 35e0ee Started GET "/posts" for 127.0.0.1 at 2025‑12‑22 23:46:30 +0000
2025-12-22T21:46:56.957795+00:00 icebox - INFO - 35e0ee Processing by PostsController#index as HTML
2025-12-22T21:46:56.957795+00:00 icebox - INFO - 35e0ee Completed 200 OK in 12ms
Each request receives a unique request id, timestamps should be in UTC (need more testing to check, Log use what timestamp).
Basic Usage
use Icebox\Log; // Add handlers (no default handlers - you must add at least one) Log::addFileHandler('log/development.log'); Log::addStdoutHandler(); // For CLI output // Log messages Log::info('User logged in'); Log::error('Database connection failed', ['db' => 'primary']); Log::debug('Processing request', ['method' => 'GET']); // All PSR-3 levels are supported: // emergency, alert, critical, error, warning, notice, info, debug
Handler Types
1. File Handler (with rotation)
Log::addFileHandler( 'log/development.log', // path 'debug', // level (optional, default: debug) 7 // max files to keep (optional, default: 7) );
2. Syslog Handler
Log::addSyslogHandler( 'myapp', // ident (optional, default: icebox) LOG_USER, // facility (optional, default: LOG_USER) 'warning' // level (optional, default: debug) );
3. Stdout Handler
Log::addStdoutHandler( 'info' // level (optional, default: debug) ); // Colorful output in CLI, plain output in web
4. Closure/ Broadcast Handler
Log::addClosureHandler(function($log) { // $log object contains: // - level: 'debug', 'info', 'warning', 'error', etc. // - message: The log message // - context: Additional context data // - channel: Logger channel name // - datetime: When the log occurred // Send to monitoring services (Sentry, Airbrake, etc.) if ($log->level === 'error') { \Sentry\captureMessage($log->message, $log->context); } // Or send to Slack, email, etc. }, 'error'); // level (optional, default: debug)
Multiple Handlers Simultaneously
// Development setup Log::addFileHandler('log/development.log'); Log::addStdoutHandler(); // Production setup Log::addFileHandler('log/production.log', 'info'); Log::addSyslogHandler('myapp-prod', 'error', LOG_USER); Log::addClosureHandler(function($log) { // Send critical errors to monitoring if (in_array($log->level, ['error', 'critical', 'alert', 'emergency'])) { sendToMonitoringService($log); } }, 'error');
Log Levels
Each handler can have its own log level:
debug: Detailed debug informationinfo: Interesting eventsnotice: Normal but significant eventswarning: Exceptional occurrences that are not errorserror: Runtime errorscritical: Critical conditionsalert: Action must be taken immediatelyemergency: System is unusable
Testing
use Icebox\Log; // Clear handlers for testing Log::clearHandlers(); // Add test handlers Log::addClosureHandler(function($log) { echo "Test log: {$log->level} - {$log->message}\n"; }); // Check handler count echo Log::handlerCount(); // 1
Notes
- No default handlers: Logs are silently ignored until handlers are added
- Multiple handlers: All added handlers receive log messages simultaneously
- Web/CLI compatibility: Works with Apache, Nginx, PHP built-in server, and CLI
- PSR-3 compliant: Interoperable with other PHP logging libraries
- Monolog under the hood: Uses the industry-standard Monolog library
How to run testsuite
You can run tests using the Icebox CLI:
php icebox test
This will run all tests in the tests folder.
To run a specific test file or folder:
php icebox test tests/create_user_test.php php icebox test tests/Feature/
Any additional arguments are passed directly to PHPUnit, so you can use PHPUnit options:
php icebox test --filter testCreateUser php icebox test tests/UserTest.php --filter testCreateUser # more specific php icebox test --filter testCreateUser php icebox test --coverage-html coverage
For more options, see php icebox test --help.
Crud generator
php icebox generate crud box
Test all column type
php icebox g crud post title:string picture:string content:text published:boolean publish_date:date create_time:datetime decimal_col:decimal float_col:float int_col:integer time_col:time
-- db schema
CREATE TABLE `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`content` text COLLATE utf8_unicode_ci,
`published` tinyint(1) DEFAULT NULL,
`publish_date` date DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`decimal_col` decimal(10,0) DEFAULT NULL,
`float_col` decimal(10,0) DEFAULT NULL,
`int_col` int(11) DEFAULT NULL,
`time_col` time DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Supported Column Types
'boolean' => array( 'html_tag' => 'checkbox', 'type' => ''),
'date' => array( 'html_tag' => 'input', 'type' => 'date'),
'datetime' => array( 'html_tag' => 'input', 'type' => 'datetime-local'),
'decimal' => array( 'html_tag' => 'input', 'type' => 'number'),
<br>
'float' => array( 'html_tag' => 'input', 'type' => 'number'),
'integer' => array( 'html_tag' => 'input', 'type' => 'number'),
'string' => array( 'html_tag' => 'input', 'type' => 'text'),
'text' => array( 'html_tag' => 'textarea', 'type' => ''),
<br>
'time' => array( 'html_tag' => 'input', 'type' => 'time'),
统计信息
- 总下载量: 7
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-12-11