# **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.*