# **Chapter 3: Installation and Project Setup** ## **3.1 System Requirements and Prerequisites** Before installing SartajPHP, ensure your development environment meets these requirements: ### **3.1.1 Server Requirements** - **PHP 7.0 or higher** (7.0+ recommended) - **Composer** (for dependency management) - **Web Server** (SphpServer, Apache 2.4+, Nginx 1.18+, or built-in PHP server) - **Extensions Required**: - PDO (with MySQL, PostgreSQL, or SQLite drivers) - JSON - MBString - OpenSSL - Zip (for Composer operations) ### **3.1.2 Optional Components** - **Node.js 14+** (for SphpDesk and npm tools) - **Redis** (for advanced caching) - **SphpServer** (for NativeGate features) - **MySQL 5.7+ / MariaDB 10.3+ / PostgreSQL 12+** (for production databases) ### **3.1.3 Development Tools** - **Git** (version control) - **VS Code** (recommended IDE with SartajPHP extension) - **Composer** (PHP package manager) - **SphpDesk** (optional desktop environment) ## **3.2 Installation Methods** SartajPHP supports multiple installation methods to suit different workflows. ### **3.2.1 Composer Installation (Recommended)** For new projects, use Composer to create a SartajPHP project: ```bash # Create a new directory for your project mkdir my-sartaj-project cd my-sartaj-project # Initialize Composer and install SartajPHP composer init --name="mycompany/myproject" --type="project" --no-interaction composer require sartajphp/sartajphp # Install sample project structure composer run-script post-install-cmd ``` This creates the following structure: ``` my-sartaj-project/ ├── vendor/sartajphp/sartajphp/ # Framework core ├── apps/ # Your applications ├── masters/ # Master templates ├── cache/ # Cache directory ├── composer.json # Dependencies ├── start.php # Entry point └── .htaccess # URL rewriting ``` ### **3.2.2 Manual Installation** For environments without Composer or custom deployments: ```bash # Download the framework wget https://github.com/sartajphp/sartajphp/releases/latest/sartajphp.zip unzip sartajphp.zip -d /var/www/myproject # Set up project structure cd /var/www/myproject cp -r res/proj1/* . ``` ### **3.2.3 Docker Installation** For containerized development: ```dockerfile # Dockerfile FROM php:8.2-apache RUN apt-get update && apt-get install -y \ git unzip libzip-dev \ && docker-php-ext-install zip pdo_mysql RUN curl -sS https://getcomposer.org/installer | php -- \ --install-dir=/usr/local/bin --filename=composer WORKDIR /var/www/html COPY . . RUN composer install EXPOSE 80 ``` Create a `docker-compose.yml`: ```yaml version: '3.8' services: app: build: . ports: - "8080:80" volumes: - .:/var/www/html - ./cache:/var/www/html/cache environment: - APP_ENV=development db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: sartajdb ``` ## **3.3 Project Structure Explained** Understanding the project structure is crucial for effective development. ### **3.3.1 Core Project Structure** ``` myproject/ ├── .htaccess # Apache/Nginx rewrite rules ├── start.php # Application entry point ├── composer.json # Dependencies and scripts ├── comp.php # Project configuration ├── reg.php # Application registry ├── cachelist.php # Cache configuration ├── prerun.php # Pre-execution hooks ├── app.sphp # Desktop app configuration │ ├── apps/ # Web applications (Gate.php files) │ ├── IndexGate.php # Main application │ ├── uuadminGate.php # Admin application │ ├── uuapiGate.php # API application │ └── fronts/ # FrontFiles for apps │ ├── index_main.front │ ├── admin_main.front │ └── api_main.front │ ├── appsn/ # NativeGate and ConsoleGate │ ├── uuchatGate.php # WebSocket chat server │ ├── uuworkerGate.php # Background worker │ └── console/ # CLI applications │ └── uubackupGate.php │ ├── masters/ # Master templates and assets │ ├── default/ # Default master set │ │ ├── master.php # Main layout │ │ ├── menu_guest.php # Guest menu │ │ └── menu_admin.php # Admin menu │ ├── db.php # Database schema │ └── sphpcodeblock.php # Custom code blocks │ ├── plugin/ # Project-specific plugins │ ├── myplugin/ │ │ ├── uupluginGate.php │ │ └── regapp.php │ └── config.json │ └── cache/ # Runtime cache ├── front/ # Compiled FrontFiles ├── component/ # Component cache ├── output/ # Page output cache └── logs/ # Error and access logs ``` ### **3.3.2 The `res/` Folder - Framework Resources** The `res/` folder contains shared framework resources. Its location depends on installation method: **Composer installation:** ``` vendor/sartajphp/sartajphp/res/ ``` **Manual installation:** ``` /path/to/framework/res/ ``` **Key subdirectories:** - `res/Score/` - Core framework engine - `res/Slib/` - Shared libraries and Components - `res/jslib/` - JavaScript libraries (jQuery, Bootstrap, etc.) - `res/components/` - Additional Components - `res/plugin/` - Framework plugins ## **3.4 Configuration Files** ### **3.4.1 `start.php` - The Entry Point** The `start.php` file is the single entry point for all requests. Never rename or remove this file. **Minimal `start.php`:** ```php <?php /** * SartajPHP Entry Point * All requests are redirected to this file via .htaccess */ // Path configuration $sharedpath = "./vendor/sartajphp/sartajphp"; $respath = "./vendor/sartajphp/sartajphp/res"; $slibversion = "Slib"; $libversion = "Sphp"; // Framework initialization (do not modify) if (!defined("start_path")) { define("start_path", __DIR__); } // Handle CLI arguments if (!isset($argvm) && isset($argv)) { global $argvm; $argvm = []; $total = count($argv); for ($c = 0; $c < $total; $c++) { $next = min($c + 1, $total - 1); if (strpos($argv[$c], "--") !== false) { if (strpos($argv[$next], "--") !== false) { $argvm[$argv[$c]] = ""; } else { $argvm[$argv[$c]] = $argv[$next]; $c++; } } } } // Allow CLI override of shared path if (isset($argv) && isset($argvm["--sharedpath"])) { chdir(start_path); $sharedpath = $argvm["--sharedpath"]; $respath = "~rs/res"; } // Load framework core $phppath = $sharedpath . "/res"; include_once("{$phppath}/Score/{$libversion}/global/start.php"); // Start engine and execute $globalapp = startSartajPHPEngine(); if ($globalapp != "") { require_once($globalapp); SphpBase::engine()->execute(true); } ``` **Customizing paths for different environments:** ```php // Development environment if ($_SERVER['HTTP_HOST'] === 'localhost') { $sharedpath = "./vendor/sartajphp/sartajphp"; $respath = "./vendor/sartajphp/sartajphp/res"; } // Production environment elseif ($_SERVER['HTTP_HOST'] === 'example.com') { $sharedpath = "/usr/share/sartajphp"; $respath = "https://cdn.example.com/sartajphp/res"; } // Staging environment else { $sharedpath = "/opt/sartajphp"; $respath = "/shared/res"; } ``` ### **3.4.2 `.htaccess` - URL Rewriting** Apache configuration for clean URLs: ```apache # .htaccess - Apache Configuration Options +FollowSymLinks -Indexes DirectoryIndex start.php RewriteEngine On # Base directory adjustment (if project is in subfolder) RewriteBase /myproject/ # Route all .html/.htm requests to start.php RewriteCond %{REQUEST_URI} \.(html|htm)$ [NC] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ start.php [NC,L] # Prevent direct access to framework files RewriteCond %{REQUEST_URI} \.(front|app|sphp)$ [NC] RewriteRule ^(.*)$ start.php [NC,L] # Force HTTPS in production RewriteCond %{HTTPS} off RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC] RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L] # Cache static assets <FilesMatch "\.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$"> Header set Cache-Control "max-age=31536000, public" </FilesMatch> ``` **Nginx configuration equivalent:** ```nginx server { listen 80; server_name example.com; root /var/www/myproject; index start.php; # Clean URLs location ~ \.(html|htm)$ { try_files $uri $uri/ /start.php?$args; } # Protect framework files location ~ \.(front|app|sphp)$ { return 403; } # PHP processing location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } # Static file caching location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } } ``` ### **3.4.3 `comp.php` - Project Configuration** The `comp.php` file contains project-wide settings: ```php <?php /** * Project Configuration File * Contains database, authentication, and global settings */ // Project Company identification $cmpid = "myproject"; $cmpname = "My Awesome Project"; $cmpemail = "info@domain.com"; $cmpaddress1 = "Address1 Lane1"; $cmpaddress2 = "Address2 ON Canada"; $cmpphone1 = "+1000-111-0000"; $cmpphone2 = "+1000-000-1111"; $basepath = ""; // Leave empty unless in subdirectory // default cache time in sec $cache_time = "100"; // javascript load type $default_filelink_load = 2; // 2= defer, 1= async, 0=nop $defenckey = "aHmlP1"; // Default Language $serv_language = "ENGLISH"; date_default_timezone_set("America/New_York"); // Session management $SESSION_NAME = 'SPHPID'; $SESSION_PATH = ''; // use default // set session state, if false you can not login $sphp_use_session = true; // single session app $sphp_use_session_storage = false; // convert session to cookie $sphp_use_session_cookie = false; // Database configuration $dhost = "localhost:3306"; $duser = "project_user"; $dpass = "secure_password"; $db = "project_db"; //$db_engine_path = $libpath . "/lib/MySQL.php,\\MySQL"; $db_engine_path = $libpath . "/lib/MySQLiPdo.php,\\MySQLiPdo"; // Debug and error reporting $debugmode = 2; // 0=production, 1=errors, 2=warnings, 3=debug $errorLog = true; // Authentication settings $admuser = 'admin'; $admpass = 'hashed_password'; // Use password_hash() in production // Master file configuration $masterf = "{$comppath}{$ComponentUI}/masters/default/master.php"; $mebmasterf = $masterf; // Email configuration $mailServerName = ""; // hostname $mailServer = "smtp.gmail.com"; // host $mailUser = "noreply@example.com"; $mailPass = "app_password"; $mailPort = "26"; $mailSecure = "no"; // tls // Authentication redirection function getWelcome() { $page = SphpBase::page(); switch ($page->getAuthenticateType()) { case "ADMIN": $page->forward(getGateURL("admhome")); break; case "MEMBER": $page->forward(getGateURL("mebhome")); break; default: $page->forward(getGateURL("index")); break; } } ``` ### **3.4.4 `reg.php` - Application Registry** The `reg.php` file maps URLs to application files: ```php <?php /** * Application Registry * Maps Gates to Application files */ // Register main applications registerGate("index", __DIR__ . "/apps/IndexGate.php"); registerGate("admin", __DIR__ . "/apps/AdminGate.php"); registerGate("api", __DIR__ . "/apps/ApiGate.php"); registerGate("auth", __DIR__ . "/apps/AuthGate.php"); // Register NativeGates registerGate("chat", __DIR__ . "/appsn/ChatGate.php", "NativeGate"); registerGate("notify", __DIR__ . "/appsn/NotificationsGate.php", "NativeGate"); // Auto-register apps (optional - for small projects) if (!SphpBase::sphp_router()->isRegisterCurrentRequest()) { $gate = SphpBase::sphp_router()->getCurrentRequest(); $appPath = PROJ_PATH . "/apps/" . ucfirst($gate) . "Gate.php"; if (is_file($appPath)) { SphpBase::sphp_router()->registerCurrentRequest($appPath); } } ``` ### **3.4.5 `prerun.php` - Pre-Execution Hooks** The `prerun.php` file runs before any application loads: ```php <?php /** * Pre-Run Configuration * Executes before any Gate loads */ class SphpPreRun extends Sphp\core\SphpPreRunP { public function onstart() { // Set global properties SphpBase::sphp_api()->addProp('site_name', 'My Project'); SphpBase::sphp_api()->addProp('current_year', date('Y')); // Security headers $policy = SphpBase::sphp_response()->getSecurityPolicy( "https://*.googleapis.com https://*.gstatic.com https://*.cloudflare.com 'self'" ); SphpBase::sphp_response()->addSecurityHeaders($policy); // Additional security headers SphpBase::sphp_response()->addHttpHeader( 'X-Content-Type-Options', 'nosniff' ); SphpBase::sphp_response()->addHttpHeader( 'X-Frame-Options', 'SAMEORIGIN' ); SphpBase::sphp_response()->addHttpHeader( 'Referrer-Policy', 'strict-origin-when-cross-origin' ); // CORS headers for API if (strpos(SphpBase::sphp_request()->server('REQUEST_URI'), '/api/') !== false) { SphpBase::sphp_response()->addHttpHeader( 'Access-Control-Allow-Origin', 'https://app.example.com' ); SphpBase::sphp_response()->addHttpHeader( 'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS' ); SphpBase::sphp_response()->addHttpHeader( 'Access-Control-Allow-Headers', 'Content-Type, Authorization' ); } // Performance headers SphpBase::sphp_response()->addHttpHeader( 'Cache-Control', 'max-age=3600, public' ); // Load global libraries $this->loadGlobalLibraries(); } private function loadGlobalLibraries() { // Auto-load Composer dependencies if (file_exists(PROJ_PATH . '/vendor/autoload.php')) { require_once PROJ_PATH . '/vendor/autoload.php'; } // Load project-specific helpers if (file_exists(PROJ_PATH . '/helpers.php')) { require_once PROJ_PATH . '/helpers.php'; } } } ``` ### **3.4.6 `cachelist.php` - Cache Configuration** Configure caching for optimal performance: ```php <?php /** * Cache Configuration * Defines caching rules for applications * You can't Cache POST Requests */ // Cache entire Gate responses addCacheList("index", 3600); // 1 hour addCacheList("blog", 1800); // 30 minutes addCacheList("shop", 7200); // 2 hours // Cache specific events addCacheList("blog-view", 3600, "ce"); // Blog view pages addCacheList("shop-product", 1800, "ce"); // Product pages // Cache with parameters (specific pages) addCacheList("blog-post-ai", 86400, "cep"); // Blog posts (1 day) addCacheList("docs-page-info", 604800, "cep"); // Documentation (1 week) // API caching (shorter TTL) addCacheList("api-products", 300, "ce"); // 5 minutes addCacheList("api-stats", 60, "ce"); // 1 minute // Disable forcefully caching for few Apps If that is in List, otherwise no need addCacheList("admin", 0); // No cache for admin addCacheList("cart", 0); // No cache for cart addCacheList("user-profile", 0, "ce"); // No cache for user profiles ``` ## **3.5 Development Environment Setup** ### **3.5.1 Local Development with PHP Built-in Server** For quick local development: ```bash # Navigate to project root cd /path/to/myproject # Start PHP server on port 8000 php -S localhost:8000 start.php # Access at http://localhost:8000/index.html ``` ### **3.5.2 SphpDesk Installation** SphpDesk is the official SartajPHP development environment: **Windows:** ```bash # Download installer curl -O https://www.sartajphp.com/pack/sphpdesk-1.7.1.exe # Run installer and follow prompts ``` **macOS/Linux:** ```bash # Install via npm npm install -g sphpdesk # Run SphpDesk sphpdesk # Run specific project sphpdesk /path/to/myproject ``` **Manual installation:** 1. Download ZIP from https://sartajphp.com/download 2. Extract to preferred location 3. Add to PATH or create desktop shortcut 4. Configure PHP path in settings ### **3.5.3 VS Code Extension** Install the SartajPHP extension for enhanced development: 1. Open VS Code 2. Go to Extensions (Ctrl+Shift+X) 3. Search for "SartajPHP" 4. Install and reload **Features include:** - Syntax highlighting for `.front` files - IntelliSense for Components and attributes - Snippets for common patterns - Project creation wizard - Debugging integration ### **3.5.4 Database Setup** Initialize your project database: ```php // masters/db.php $mysql = SphpBase::dbEngine(); $mysql->connect(); // Create users table $sql = "CREATE TABLE IF NOT EXISTS users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, role ENUM('admin', 'member', 'guest') DEFAULT 'guest', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_email (email), INDEX idx_role (role) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"; $mysql->createTable($sql); // Create posts table $sql = "CREATE TABLE IF NOT EXISTS posts ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, title VARCHAR(200) NOT NULL, content TEXT NOT NULL, slug VARCHAR(200) UNIQUE NOT NULL, status ENUM('draft', 'published', 'archived') DEFAULT 'draft', published_at TIMESTAMP NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, INDEX idx_slug (slug), INDEX idx_status (status), INDEX idx_user (user_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"; $mysql->createTable($sql); // Insert default admin user (password: admin123) $mysql->executeQuery( "INSERT IGNORE INTO users (username, email, password_hash, role) VALUES ('admin', 'admin@example.com', '". password_hash('admin123', PASSWORD_DEFAULT) ."', 'admin')" ); $mysql->disconnect(); ``` Run the database initialization: ```bash # Via CLI php start.php --gate install --evt db # Or via browser # you may be need login as ADMIN # Access http://localhost/myproject/install-db.html ``` ## **3.6 Production Deployment** ### **3.6.1 Deployment Checklist** Before deploying to production: 1. **Update configuration:** ```php // In comp.php $debugmode = 0; // Disable debug mode ``` 2. **Set secure permissions:** ```bash chmod 755 /var/www/myproject chmod 644 /var/www/myproject/*.php chmod 777 /var/www/myproject/cache # Writeable for cache chown www-data:www-data /var/www/myproject -R ``` 3. **Enable HTTPS:** ```apache # .htaccess RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L] ``` 4. **Configure production database:** ```php // In comp.php $dhost = "production-db.example.com"; $duser = "prod_user"; $dpass = "strong_password_here"; $db = "production_db"; ``` ### **3.6.2 Deployment Script** Create a deployment script (`deploy.sh`): ```bash #!/bin/bash # deploy.sh - Production deployment script set -e # Exit on error echo "Starting deployment..." # Pull latest code git pull origin main # Install dependencies composer install --no-dev --optimize-autoloader # Clear cache (in case of file changes) rm -rf cache/* # Set permissions chmod -R 755 . chmod -R 777 cache # Run database migrations if needed php start.php --gate migrate --evt run # Restart services sudo systemctl restart apache2 sudo systemctl restart sphp-server # If using NativeGate echo "Deployment complete!" ``` ### **3.6.3 Environment-Based Configuration** For different environments, use environment variables: ```php // Detect environment $env = getenv('APP_ENV') ?: 'development'; // Load environment-specific config switch ($env) { case 'production': $config = require 'config/production.php'; break; case 'staging': $config = require 'config/staging.php'; break; default: $config = require 'config/development.php'; break; } // Apply to comp.php settings $debugmode = $config['debug'] ? 2 : 0; $dhost = $config['database']['host']; // ... etc ``` ## **3.7 Troubleshooting Common Setup Issues** ### **3.7.1 "File Not Found" Errors** **Problem:** URLs return 404 errors even though files exist. **Solution:** 1. Check `.htaccess` file exists and is readable 2. Ensure Apache `mod_rewrite` is enabled: ```bash sudo a2enmod rewrite sudo systemctl restart apache2 ``` 3. Verify Apache configuration allows `.htaccess` overrides: ```apache <Directory /var/www/myproject> AllowOverride All Require all granted </Directory> ``` ### **3.7.2 Permission Denied for Cache** **Problem:** "Permission denied" errors when writing to cache directory. **Solution:** ```bash # Set correct ownership sudo chown www-data:www-data /path/to/project/cache -R sudo chmod 775 /path/to/project/cache # Or for development (less secure) chmod 777 /path/to/project/cache ``` ### **3.7.3 Database Connection Errors** **Problem:** Cannot connect to database. **Solution:** 1. Verify credentials in `comp.php` 2. Check database server is running 3. Ensure PDO extension is installed: ```bash php -m | grep pdo ``` 4. Test connection manually: ```php <?php try { $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); echo "Connected successfully"; } catch (PDOException $e) { echo "Connection failed: " . $e->getMessage(); } ``` ### **3.7.4 Components Not Loading** **Problem:** Components with `runat="server"` don't work. **Solution:** 1. Check PHP version (requires 7.0+) 2. Verify `res/` path is correct in `start.php` 3. Check file permissions on Component classes 4. Clear cache: `rm -rf cache/*` ## **3.8 Chapter Summary** In this chapter, we've covered: 1. **System Requirements** - What you need to run SartajPHP 2. **Installation Methods** - Composer, manual, and Docker options 3. **Project Structure** - Understanding the directory layout 4. **Configuration Files** - Setting up `start.php`, `.htaccess`, `comp.php`, etc. 5. **Development Environment** - Tools and setup for efficient development 6. **Production Deployment** - Best practices for going live 7. **Troubleshooting** - Solving common setup issues With your environment properly configured, you're ready to start building applications. In the next chapter, we'll dive into the heart of SartajPHP: the Event-Oriented Paradigm and how to structure your applications around events rather than controllers. --- *Next: Chapter 4 explores the Event-Oriented Paradigm in depth, showing how to design applications around PageEvents rather than traditional MVC controllers.*