vnbase / vnbiz
My simple library
Installs: 10
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/vnbase/vnbiz
Requires
- php: >=7.0.0
This package is auto-updated.
Last update: 2026-02-11 14:48:31 UTC
README
A PHP framework for building RESTful APIs with built-in authentication, permissions, file uploads, caching, and multi-tenancy support.
Requirements
- PHP >= 7.0
- MySQL
- Redis (optional, for caching and editing locks)
- Imagick PHP extension (optional, for image processing)
Installation
composer require vnbase/vnbiz
Quick Start
require 'vendor/autoload.php'; // Initialize vnbiz()->init_app('my_app', 'my_jwt_secret'); vnbiz()->init_db_mysql('localhost', 'user', 'pass', 'database'); // Define models vnbiz_model_add('project') ->string('name', 'code') ->text('description') ->enum('status', ['active', 'archived'], 'active') ->ref('owner_id', 'user') ->require('name') ->author() ->text_search('name', 'description'); // Start the framework vnbiz()->start(); // Run migrations vnbiz_sql_alter_tables(); // Handle API requests vnbiz()->handle_restful();
Architecture
Project Structure
src/
vnbiz.php # Bootstrap entry point
base/
rb.php # RedBeanPHP ORM
jwt.php # JWT token implementation (HS256)
logger.php # Monolog logger setup
div.php # Div template engine
vndb.php # Lightweight DB layer (alternative)
hashids/ # Hashids library for ID encryption
core/
VnBiz.php # Main singleton class
vnbiz_functions.php # Global utility functions
Model.php # Model definition with fluent API
Model_event.php # Event hook trait
Model_permission.php # Permission control trait
Schema.php # Schema definition class
Actions.php # Action/event dispatcher
VnBiz_restful.php # RESTful API handler trait
VnBiz_sql.php # SQL/database operations trait
VnBizError.php # Custom exception class
VnbizImage.php # Image manipulation (Imagick)
modules/
user.php # User authentication & authorization
oauth.php # Google OAuth integration
email.php # Email sending & templating
comment.php # Comment system
history.php # Audit trail
notification.php # User notifications
redis.php # Redis integration & request tracking
s3.php # AWS S3 file uploads
tag.php # Tagging system
review.php # Rating/review system
monitor.php # System monitoring
datascope.php # Row-level access control
editing_by.php # Concurrent editing locks
namespace.php # Multi-tenancy support
jsonschema.php # JSON Schema generation
typescriptschema.php # TypeScript interface generation
template.php # Template rendering (Div engine)
sql.php # SQL schema migration
systemconfig.php # Key-value config storage
useractivity.php # User activity logging
usermark.php # User bookmarks/likes
Request Lifecycle
HTTP Request
-> handle_restful()
-> Parse action (model_create, model_find, service_*, etc.)
-> web_before_{action}_{model_name}
-> Permission checks
-> model_{action}
-> db_before_{action}
-> BEGIN TRANSACTION
-> db_begin_{action}
-> [DATABASE OPERATION]
-> db_before_commit_{action}
-> COMMIT
-> db_after_commit_{action}
-> [ROLLBACK on error]
-> db_rollback_{action}
-> db_end_{action}
-> db_after_{action}
-> web_after_{action}_{model_name}
-> JSON Response
Initialization
Database (MySQL)
vnbiz()->init_db_mysql('host', 'user', 'password', 'database');
Redis (optional)
vnbiz()->init_redis('127.0.0.1', 6379, 'password');
Enables single-record query caching, editing locks, and request counters.
AWS S3 (optional)
vnbiz()->init_aws('region', 'bucket', 'access_key', 'secret_key');
Email / SMTP (optional)
vnbiz()->init_mailer('smtp.example.com', 465, 'user@example.com', 'password');
Falls back to PHP mail() if not configured.
Google OAuth (optional)
vnbiz()->init_oauth_google('client_id', 'client_secret', 'redirect_uri');
Modules
vnbiz()->init_modules(['email', 'comment', 'history', 'notification', 's3', 'tag', 'review']);
Multi-Tenancy
vnbiz()->use_namespaces(['project', 'task']); // models that are namespace-scoped
Namespace ID is extracted from: X-Namespace header, ns GET param, or ns POST param.
Model Definition
Models are defined using a fluent API.
Field Types
vnbiz_model_add('product') ->string('name', 'sku') // VARCHAR(255) ->text('description') // LONGTEXT ->int('quantity') // BIGINT ->uint('price') // BIGINT UNSIGNED ->float('weight') // FLOAT ->bool('is_active') // BOOLEAN ->date('release_date') // DATE ->datetime('published_at') // BIGINT UNSIGNED (ms timestamp) ->json('metadata') // JSON stored as LONGTEXT ->email('contact_email') // VARCHAR(255) with email validation ->slug('url_slug') // Lowercase alphanumeric, hyphens, underscores ->password('secret'); // Hashed with bcrypt
Enums and Status
->enum('priority', ['low', 'medium', 'high'], 'medium') // Status with state machine flow ->status('status', [ 'draft' => ['review'], 'review' => ['approved', 'rejected'], 'approved' => ['published'], 'rejected' => ['draft'], 'published' => [] ], 'draft')
References (Foreign Keys)
->ref('category_id', 'category') // Reference to another model ->ref('owner_id', 'user') ->model_name('target_model') // Stores a model name string ->model_id('target_id') // Stores a model ID
Constraints
->require('name', 'sku') // Required fields ->default(['is_active' => true]) // Default values ->unique('idx_sku', ['sku']) // Unique constraint ->index('idx_category', ['category_id']) // Database index ->no_create('computed_field') // Cannot set on create ->no_update('sku') // Cannot update after creation ->no_delete() // Prevent deletion entirely
Built-in Features
->author() // Adds created_by, updated_by (auto-populated from logged-in user) ->has_v() // Optimistic locking with version field ->has_trash() // Soft delete (status: active/trash) ->has_tags() // Tagging system ->has_comments(true) // Comment system ->has_history() // Audit trail (snapshots on update) ->has_reviews() // Rating/review system (1-5 stars) ->has_usermarks('like', 'bookmark') // User marks with auto-counters ->has_datascope() // Row-level access control ->has_editing_by() // Concurrent editing lock (via Redis) ->text_search('name', 'description') // Full-text search index
File Uploads (S3)
->s3_image('photo', 800, 400, 200) // Image with multiple sizes (width) ->s3_file('attachment') // Generic file upload
Denormalized Counters
->back_ref_count('task_count', 'task', 'project_id') // Automatically maintains task_count when tasks are created/deleted
Permissions
->create_permission('admin', 'editor') ->read_permission('viewer', 'editor', 'admin') ->update_permission('editor', 'admin') ->delete_permission('admin') ->write_permission('admin') // Shorthand for create + update + delete // Owner-based: users can always read/write their own records ->read_permission_or_user_id('admin', 'created_by') ->write_permission_or_user_id('admin', 'created_by') // Custom permission check ->update_permission_or(['editor'], function(&$context) { return $context['model']['owner_id'] === vnbiz_user_id(); }) // Field-level permissions ->read_field_permission(['salary', 'ssn'], 'hr', 'admin') ->write_field_permission(['role'], 'admin')
Users with the super permission bypass all permission checks.
Event Hooks
$model = vnbiz_model_add('order'); // Web layer hooks (before/after HTTP handling) $model->web_before_create(function(&$context) { /* validate */ }); $model->web_after_create(function(&$context) { /* notify */ }); $model->web_before_update(function(&$context) { /* check */ }); $model->web_after_find(function(&$context) { /* transform */ }); // Database layer hooks (within transaction) $model->db_before_create(function(&$context) { /* pre-insert logic */ }); $model->db_begin_create(function(&$context) { /* start of transaction */ }); $model->db_after_create(function(&$context) { /* post-insert logic */ }); $model->db_after_commit_create(function(&$context) { /* after commit */ }); $model->db_end_create(function(&$context) { /* cleanup */ }); // After fetch (for computed fields) $model->db_after_fetch(function(&$context) { foreach ($context['models'] as &$m) { $m['display_name'] = $m['first_name'] . ' ' . $m['last_name']; } });
UI Metadata
->ui([ 'icon' => 'folder', 'label' => 'Projects', 'fields' => [ 'name' => ['label' => 'Project Name'], ] ]) ->web_readonly('computed_score') // Read-only in web API ->system_field('internal_flag') // Marked as system field
RESTful API
Endpoint
All requests go through a single endpoint:
POST /api
Content-Type: application/json
Authorization: Bearer <access_token>
Actions
Create
{
"action": "model_create",
"model_name": "project",
"model": {
"name": "My Project",
"description": "A new project"
}
}
Find
{
"action": "model_find",
"model_name": "project",
"filter": {
"status": "active"
},
"meta": {
"limit": 10,
"offset": 0,
"order": "-created_at",
"count": true,
"ref": true,
"text_search": "keyword"
}
}
Count
{
"action": "model_count",
"model_name": "project",
"filter": {
"status": "active"
}
}
Update
{
"action": "model_update",
"model_name": "project",
"filter": { "id": "abc123" },
"model": {
"name": "Updated Name"
}
}
Delete
{
"action": "model_delete",
"model_name": "project",
"filter": { "id": "abc123" }
}
Service Call
{
"action": "service_user_login",
"params": {
"username": "admin",
"password": "secret"
}
}
Filter Operators
{
"filter": {
"price": { "$gt": 100 },
"price": { "$gte": 100 },
"price": { "$lt": 500 },
"price": { "$lte": 500 },
"status": ["active", "pending"],
"category_id": "encrypted_id"
}
}
Response Format
{
"code": "ok",
"models": [...],
"count": 42
}
Error response:
{
"code": "error",
"error": "permission",
"error_message": "Permission denied",
"error_fields": {
"name": "Name is required"
}
}
Authentication
Built-in Models
The user module provides three models:
- user - User accounts (alias, email, username, password, avatar, etc.)
- usergroup - Permission groups (name, permissions, permissions_scope)
- useringroup - User-to-group mapping (many-to-many)
Token System
- Access Token (JWT, 15-minute expiry): Contains user ID, permissions, and permission scopes
- Refresh Token (JWT): Used to obtain new access tokens
Services
Login
{
"action": "service_user_login",
"params": {
"username": "admin",
"password": "secret"
}
}
Refresh Token
{
"action": "service_user_login",
"params": {
"refresh_token": "<token>"
}
}
Get Current User
{
"action": "service_user_me"
}
Google OAuth
{ "action": "service_oauth_google_url" }
{ "action": "service_oauth_google_login", "params": { "code": "<oauth_code>" } }
Helper Functions
vnbiz_user() // Get current user (or null) vnbiz_user_id() // Get current user ID (or null) vnbiz_user_or_throw() // Require authentication vnbiz_user_has_permissions('admin') // Check permission vnbiz_assure_user_has_permissions('admin') // Throw if missing vnbiz_user_all_permissions($user_id) // Get all permissions for a user
Default Admin
{ "action": "service_db_init_default" }
Creates a default superadmin user (superadmin / 1) if no users exist.
Modules
Comment
Nested comment system for any model with has_comments(true).
Fields: model_name, model_id, title, content, parent_comment_id, image, file.
History
Audit trail for models with has_history(). Stores full JSON snapshots on update. No update or delete allowed on history records.
Notification
User notification system.
vnbiz_notification_create($user_id, $title, $content, $payload);
Fields: user_id, title, content, payload (JSON), status (new/viewed).
Also provides notificationtoken model for push notification tokens (FCM/APNs).
Tag
Tagging system for models with has_tags().
vnbiz_model_set_tags('project', $id, ['php', 'api']); vnbiz_model_get_tags('project', $id); vnbiz_model_remove_tags('project', $id, ['old-tag']);
Review
Rating/review system for models with has_reviews(). Supports 1-5 star ratings. Automatically maintains review_count, review_count_1..review_count_5, and review_rate on the target model.
Usermark
Bookmark/like system for models with has_usermarks('like', 'bookmark'). Automatically maintains counter fields (number_of_like, number_of_bookmark) and per-user flags (@like_by_me, @bookmark_by_me).
Datascope
Hierarchical row-level access control for models with has_datascope().
Scope format: . (root), .1. (department 1), .1.2. (sub-department). A user with scope .1. can access all rows with scopes .1., .1.2., .1.3., etc. Scopes are stored in the user's permissions_scope.
Editing Lock
Concurrent editing prevention for models with has_editing_by(). Uses Redis with a 15-second TTL. Requires has_v() for optimistic locking.
{ "action": "service_editing_by_me", "params": { "model_name": "project", "model_id": "abc" } }
Namespace (Multi-Tenancy)
Adds a ns field to specified models. All queries are automatically filtered by namespace. Namespace ID comes from the X-Namespace header or ns parameter.
Email sending with template support via the Div template engine.
vnbiz_mail_template_to_user($user_id, 'welcome_email', 'en', ['name' => 'John']); vnbiz_mail_content_template($to_email, $to_name, $subject, $content, $data);
Template
Named templates stored in database with language support.
vnbiz_render('welcome_email', 'en', ['name' => 'John'], 'Hello {$name}');
S3
AWS S3 file uploads with automatic thumbnail generation.
// On model definition ->s3_image('avatar', 800, 200) // Generates 800px and 200px versions ->s3_file('document') // Generic file upload
Uploaded files get signed URLs with 24-hour expiry.
Redis
vnbiz_redis() // Get Redis connection vnbiz_redis_get_array($key) // Get JSON value vnbiz_redis_set_array($key, $data, $ttl) // Set JSON value (default 1hr TTL) vnbiz_redis_del($key) // Delete key
Also tracks request counters per action/model for monitoring.
System Config
Key-value configuration stored in database.
vnbiz_systemconfig_set('site_name', 'My App'); vnbiz_systemconfig_get('site_name'); // 'My App'
Monitor
vnbiz_monitor(); // Display system stats (hostname, CPU, memory, load) vnbiz_monitor_request(); // Display per-action request counters from Redis
Schema Generation
vnbiz_echo_jsonschema(); // Output JSON Schema (Draft 2020-12) vnbiz_echo_typescript_schema(); // Output TypeScript interfaces
SQL Migrations
// Generate SQL without executing $sql = vnbiz_sql_generate(); // Generate and execute migrations vnbiz_sql_alter_tables(); // Generate, execute, and echo output vnbiz_sql_alter_tables_echo();
Migrations automatically add/modify columns and indexes. Existing data is preserved.
Utility Functions
// Safe variable access vnbiz_get_var($var, $default) vnbiz_get_key($array, 'key', $default) // ID encryption (Hashids) vnbiz_encrypt_id(42) // -> 'xYz123' vnbiz_decrypt_id('xYz123') // -> 42 // Action system vnbiz_do_action('my_action', $context) vnbiz_add_action('my_action', function(&$ctx) { /* ... */ }) vnbiz_do_service('my_service', ['param' => 'value']) // Misc vnbiz_now() // Current UTC datetime string vnbiz_random_string(32) // Random alphanumeric string vnbiz_unique_text() // Unique 32-char hex string vnbiz_generate_thumbnail($src, $dst, $w, $h) // Create thumbnail (Imagick)
Services
Built-in Services
| Service | Description |
|---|---|
service_health_check |
Check MySQL and Redis connectivity |
service_sys_schemas |
Return all model schemas |
service_user_login |
Login with username/password or refresh token |
service_user_me |
Get current authenticated user |
service_user_logout |
Logout |
service_db_init_default |
Create default superadmin user |
service_oauth_google_url |
Get Google OAuth authorization URL |
service_oauth_google_login |
Exchange OAuth code for tokens |
service_editing_by_me |
Claim editing lock on a record |
Custom Services
vnbiz_add_action('service_my_custom', function(&$context) { $params = $context['params']; // ... business logic ... $context['models'] = [$result]; });
Error Handling
Errors are thrown as VnBizError exceptions with structured information:
throw new VnBizError('Item not found', 'not_found'); throw new VnBizError('Validation failed', 'invalid', ['name' => 'Name is required']); throw new VnBizError('Forbidden', 'permission'); // HTTP 403
The RESTful handler catches all exceptions and returns proper JSON error responses with appropriate HTTP status codes.
Logging
L()->debug('message'); L()->info('message'); L()->error('message'); L_withName('MyModule'); // Set logger context vnbiz_debug_enabled(); // Check if debug mode is on
Debug mode is enabled via the VNBIZ_DEBUG environment variable or debug GET parameter.
License
Apache-2.0