Examples
Hello World
<?php
echo "Hello, VHP!\n";
Variables and Math
<?php
$a = 10;
$b = 5;
$c = ($a + $b) * 2 - $a / $b;
echo $c; // Output: 28
Mixed HTML/PHP
<!DOCTYPE html>
<html>
<body>
<h1><?= "Welcome to VHP!" ?></h1>
<?php
$items = 3;
echo "<p>You have $items items.</p>";
?>
</body>
</html>
Null Safety
<?php
$config = null;
$timeout = $config ?? 30;
echo "Timeout: $timeout"; // Output: Timeout: 30
FizzBuzz
<?php
for ($i = 1; $i <= 100; $i++) {
if ($i % 15 == 0) {
echo "FizzBuzz\n";
} elseif ($i % 3 == 0) {
echo "Fizz\n";
} elseif ($i % 5 == 0) {
echo "Buzz\n";
} else {
echo $i . "\n";
}
}
Factorial (Recursive)
<?php
function factorial($n) {
if ($n <= 1) return 1;
return $n * factorial($n - 1);
}
echo "5! = " . factorial(5) . "\n"; // 120
echo "10! = " . factorial(10) . "\n"; // 3628800
Fibonacci Sequence
<?php
function fibonacci($n) {
if ($n <= 1) return $n;
return fibonacci($n - 1) + fibonacci($n - 2);
}
echo "Fibonacci sequence: ";
for ($i = 0; $i < 10; $i++) {
echo fibonacci($i);
if ($i < 9) echo ", ";
}
// Output: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
String Manipulation
<?php
$text = " Hello, World! ";
echo strlen($text) . "\n"; // 17
echo trim($text) . "\n"; // "Hello, World!"
echo strtoupper($text) . "\n"; // " HELLO, WORLD! "
echo str_replace("World", "VHP", $text) . "\n"; // " Hello, VHP! "
echo strrev(trim($text)) . "\n"; // "!dlroW ,olleH"
Temperature Converter
<?php
function celsiusToFahrenheit($c) {
return $c * 9 / 5 + 32;
}
function fahrenheitToCelsius($f) {
return ($f - 32) * 5 / 9;
}
$celsius = 100;
$fahrenheit = 32;
echo $celsius . "°C = " . celsiusToFahrenheit($celsius) . "°F\n";
echo $fahrenheit . "°F = " . fahrenheitToCelsius($fahrenheit) . "°C\n";
Prime Number Checker
<?php
function isPrime($n) {
if ($n < 2) return false;
if ($n == 2) return true;
if ($n % 2 == 0) return false;
$i = 3;
while ($i * $i <= $n) {
if ($n % $i == 0) return false;
$i += 2;
}
return true;
}
echo "Primes up to 50: ";
for ($i = 2; $i <= 50; $i++) {
if (isPrime($i)) {
echo $i . " ";
}
}
// Output: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
Fibers (Cooperative Multitasking)
<?php
function worker($name) {
echo "Worker $name starting\n";
for ($i = 1; $i <= 3; $i++) {
echo "Worker $name: Step $i\n";
// Suspend execution and pass control back
$data = Fiber::suspend("step_$i");
if ($data) {
echo "Worker $name received: $data\n";
}
}
return "Worker $name completed";
}
$fiber = new Fiber('worker');
// Start the fiber
$result = $fiber->start('Alice');
echo "Fiber returned: $result\n";
// Resume multiple times
$result = $fiber->resume('resume_1');
echo "Fiber returned: $result\n";
$result = $fiber->resume('resume_2');
echo "Fiber returned: $result\n";
$result = $fiber->resume('resume_3');
echo "Final result: $result\n";
// Check final state
echo "Terminated: " . ($fiber->isTerminated() ? "Yes" : "No") . "\n";
Exception Handling
<?php
class ValidationException extends Exception {}
class DatabaseException extends Exception {}
function processUser($username, $age) {
// Validate input
if (empty($username)) {
throw new ValidationException("Username cannot be empty");
}
if ($age < 0 || $age > 150) {
throw new ValidationException("Invalid age: " . $age);
}
// Simulate database operation
if ($username === "admin") {
throw new DatabaseException("Cannot modify admin user");
}
return "User $username (age $age) processed successfully";
}
// Example 1: Catch specific exception
try {
echo processUser("", 25);
} catch (ValidationException $e) {
echo "Validation Error: " . $e->getMessage() . "\n";
} catch (DatabaseException $e) {
echo "Database Error: " . $e->getMessage() . "\n";
}
// Output: Validation Error: Username cannot be empty
// Example 2: Multi-catch (PHP 7.1+)
try {
echo processUser("admin", 30);
} catch (ValidationException | DatabaseException $e) {
echo "Error: " . $e->getMessage() . "\n";
}
// Output: Error: Cannot modify admin user
// Example 3: Finally block always executes
function attemptOperation() {
try {
echo "Opening connection\n";
throw new Exception("Connection failed");
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
} finally {
echo "Closing connection\n";
}
}
attemptOperation();
// Output:
// Opening connection
// Error: Connection failed
// Closing connection
// Example 4: Throw as expression (PHP 8.0+)
function getConfig($key) {
$config = ["timeout" => 30, "retries" => 3];
return $config[$key] ?? throw new Exception("Config key '$key' not found");
}
try {
echo "Timeout: " . getConfig("timeout") . "\n";
echo getConfig("invalid");
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// Output:
// Timeout: 30
// Error: Config key 'invalid' not found
DNF Types (PHP 8.2)
DNF (Disjunctive Normal Form) types allow complex type declarations that combine union and intersection types.
<?php
// Example 1: Basic DNF type - (A&B)|C
interface Loggable {
public function log();
}
interface Serializable {
public function serialize();
}
interface Cacheable {
public function cache();
}
// Accept either (Loggable AND Serializable) OR Cacheable
function process((Loggable&Serializable)|Cacheable $obj): void {
if ($obj instanceof Loggable) {
$obj->log();
}
if ($obj instanceof Cacheable) {
$obj->cache();
}
}
class LogSerializable implements Loggable, Serializable {
public function log() { echo "Logged\n"; }
public function serialize() { return "serialized"; }
}
class Cache implements Cacheable {
public function cache() { echo "Cached\n"; }
}
process(new LogSerializable()); // OK: matches (Loggable&Serializable)
process(new Cache()); // OK: matches Cacheable
// Example 2: Multiple intersection groups - (A&B)|(C&D)
interface Iterator {}
interface Countable {}
interface ArrayAccess {}
interface Traversable {}
class CountableIterator implements Iterator, Countable {}
class TraversableArray implements ArrayAccess, Traversable {}
function handle((Iterator&Countable)|(ArrayAccess&Traversable) $collection): string {
return get_class($collection);
}
echo handle(new CountableIterator()) . "\n"; // CountableIterator
echo handle(new TraversableArray()) . "\n"; // TraversableArray
// Example 3: DNF with return types
interface Readable {
public function read();
}
interface Writable {
public function write($data);
}
interface Stream {
public function stream();
}
class File implements Readable, Writable {
public function read() { return "data"; }
public function write($data) {}
}
function openResource(): (Readable&Writable)|Stream {
return new File();
}
$resource = openResource();
echo $resource->read(); // data
// Example 4: Type validation with DNF
interface A {}
interface B {}
interface C {}
class AB implements A, B {}
class OnlyA implements A {}
function test((A&B)|C $obj): void {
echo "Valid type\n";
}
test(new AB()); // Valid type
// test(new OnlyA()); // TypeError: Expected type (A&B)|C
// OnlyA only implements A, not both A and B, and not C
// Example 5: Complex business logic with DNF
interface PaymentMethod {
public function charge($amount);
}
interface Refundable {
public function refund($amount);
}
interface Recurring {
public function setupRecurring($interval);
}
class CreditCard implements PaymentMethod, Refundable {
public function charge($amount) { return "Charged $amount"; }
public function refund($amount) { return "Refunded $amount"; }
}
class Subscription implements Recurring {
public function setupRecurring($interval) { return "Recurring: $interval"; }
}
function processPayment((PaymentMethod&Refundable)|Recurring $method): string {
if ($method instanceof PaymentMethod) {
return $method->charge(100);
} elseif ($method instanceof Recurring) {
return $method->setupRecurring("monthly");
}
return "Unknown";
}
echo processPayment(new CreditCard()) . "\n"; // Charged 100
echo processPayment(new Subscription()) . "\n"; // Recurring: monthly
Declare Strict Types (PHP 7.0)
The declare(strict_types=1) directive enables strict type checking, preventing automatic type coercion.
<?php
// Example 1: Strict types enabled
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
echo add(5, 10); // OK: 15
echo add(5.0, 10); // TypeError: must be of type int, float given
echo add("5", 10); // TypeError: must be of type int, string given
// Example 2: Without strict types (default coercive mode)
function multiply(int $a, int $b): int {
return $a * $b;
}
echo multiply("5", "10"); // OK: 50 (strings coerced to integers)
echo multiply(5.9, 2.1); // OK: 10 (floats truncated: 5 * 2)
// Example 3: Type widening exception - int to float is allowed
declare(strict_types=1);
function divide(float $a, float $b): float {
return $a / $b;
}
echo divide(10, 2); // OK: 5 (int widened to float)
echo divide(10.0, 2.0); // OK: 5
echo divide("10", 2); // TypeError: string cannot be passed as float
// Example 4: Strict validation for multiple types
declare(strict_types=1);
function processUser(string $name, int $age, bool $active): string {
$status = $active ? "active" : "inactive";
return "$name is $age years old ($status)";
}
echo processUser("Alice", 30, true) . "\n"; // OK
echo processUser("Bob", "25", true); // TypeError: age must be int
// Example 5: Block-scoped strict types
function coercive(int $x): int {
return $x;
}
declare(strict_types=1) {
function strict(int $x): int {
return $x;
}
// strict() enforces strict types
// echo strict("10"); // TypeError
}
// coercive() uses default type coercion
echo coercive("10"); // OK: 10
Property Hooks (PHP 8.4)
Property hooks provide a clean way to add custom logic to property access without explicit getter/setter methods.
<?php
// Example 1: Computed property with get hook
class Circle {
public float $radius = 5.0;
public float $diameter {
get => $this->radius * 2;
}
public float $area {
get => 3.14159 * $this->radius ** 2;
}
}
$c = new Circle();
echo "Radius: " . $c->radius . "\n"; // 5
echo "Diameter: " . $c->diameter . "\n"; // 10
echo "Area: " . $c->area . "\n"; // 78.53975
$c->radius = 10.0;
echo "New diameter: " . $c->diameter . "\n"; // 20 (automatically updated)
// Example 2: Temperature converter with get and set hooks
class Temperature {
private float $celsius = 0;
public float $fahrenheit {
get => $this->celsius * 9/5 + 32;
set {
$this->celsius = ($value - 32) * 5/9;
}
}
}
$t = new Temperature();
$t->fahrenheit = 212;
echo "Fahrenheit: " . $t->fahrenheit . "\n"; // 212
echo "Celsius: " . $t->celsius . "\n"; // 100
// Example 3: Validation and logging with set hook
class User {
private string $rawEmail = "";
public string $email {
get => $this->rawEmail;
set {
if (!str_contains($value, "@")) {
throw new Exception("Invalid email format");
}
$this->rawEmail = strtolower($value);
echo "Email set to: " . $this->rawEmail . "\n";
}
}
}
$user = new User();
$user->email = "USER@EXAMPLE.COM"; // Email set to: user@example.com
echo "Current: " . $user->email . "\n"; // user@example.com
// Example 4: Read-only computed property
class Rectangle {
public float $width = 10.0;
public float $height = 5.0;
public float $area {
get => $this->width * $this->height;
}
}
$rect = new Rectangle();
echo "Area: " . $rect->area . "\n"; // 50
// $rect->area = 100; // Error: Cannot set property with only get hook
// Example 5: Side-effects with set hooks
class EventLogger {
private array $events = [];
public string $event {
set {
$this->events[] = [
"message" => $value,
"timestamp" => date("Y-m-d H:i:s")
];
echo "Logged event: " . $value . "\n";
}
}
}
$logger = new EventLogger();
$logger->event = "User logged in"; // Logged event: User logged in
$logger->event = "Data processed"; // Logged event: Data processed
Static Properties and Late Static Binding (PHP 5.0/5.3)
Static properties are class-level variables shared across all instances. Late static binding allows proper inheritance behavior with the static:: keyword.
<?php
// Example 1: Basic static property counter
class PageView {
public static $count = 0;
public static function recordView() {
self::$count++;
echo "Total views: " . self::$count . "\n";
}
}
PageView::recordView(); // Total views: 1
PageView::recordView(); // Total views: 2
PageView::recordView(); // Total views: 3
// Example 2: Configuration management with static properties
class Config {
private static $settings = [
"debug" => false,
"cache" => true
];
public static function get($key) {
return self::$settings[$key] ?? null;
}
public static function set($key, $value) {
self::$settings[$key] = $value;
}
}
echo "Debug mode: " . (Config::get("debug") ? "on" : "off") . "\n"; // off
Config::set("debug", true);
echo "Debug mode: " . (Config::get("debug") ? "on" : "off") . "\n"; // on
// Example 3: Late static binding with static::
class Animal {
protected static $species = "Unknown";
public static function getSpecies() {
// static:: refers to the called class (late binding)
return static::$species;
}
public static function identify() {
echo "I am a " . static::getSpecies() . "\n";
}
}
class Dog extends Animal {
protected static $species = "Canine";
}
class Cat extends Animal {
protected static $species = "Feline";
}
Animal::identify(); // I am a Unknown
Dog::identify(); // I am a Canine
Cat::identify(); // I am a Feline
// Example 4: Difference between self:: and static::
class Counter {
protected static $name = "Base Counter";
public static function showWithSelf() {
return "self:: -> " . self::$name;
}
public static function showWithStatic() {
return "static:: -> " . static::$name;
}
}
class SpecialCounter extends Counter {
protected static $name = "Special Counter";
}
echo Counter::showWithSelf() . "\n"; // self:: -> Base Counter
echo Counter::showWithStatic() . "\n"; // static:: -> Base Counter
echo SpecialCounter::showWithSelf() . "\n"; // self:: -> Base Counter (wrong!)
echo SpecialCounter::showWithStatic() . "\n"; // static:: -> Special Counter (correct!)
// Example 5: Singleton pattern with static properties
class Database {
private static $instance = null;
private $connectionString;
private function __construct($connStr) {
$this->connectionString = $connStr;
echo "Database connected to: " . $connStr . "\n";
}
public static function getInstance($connStr = "localhost:5432") {
if (self::$instance === null) {
self::$instance = new Database($connStr);
}
return self::$instance;
}
public function query($sql) {
echo "Executing: " . $sql . "\n";
}
}
$db1 = Database::getInstance("production.db");
$db1->query("SELECT * FROM users");
$db2 = Database::getInstance("another.db"); // Reuses existing instance
$db2->query("SELECT * FROM posts");
// Example 6: Static property with array operations
class Registry {
public static $data = [];
public static function register($key, $value) {
self::$data[$key] = $value;
}
public static function get($key) {
return self::$data[$key] ?? null;
}
}
Registry::register("app_name", "VHP Framework");
Registry::register("version", "1.0.0");
echo "App: " . Registry::get("app_name") . "\n"; // App: VHP Framework
echo "Version: " . Registry::get("version") . "\n"; // Version: 1.0.0
Asymmetric Visibility (PHP 8.4)
Asymmetric visibility allows public read access with restricted write access, eliminating the need for getter/setter boilerplate.
<?php
// Example 1: Basic asymmetric visibility - public read, private write
class User {
public private(set) string $id;
public private(set) string $email;
public string $name; // Symmetric: public read/write
public function __construct(string $id, string $email, string $name) {
$this->id = $id; // OK: write inside class
$this->email = $email;
$this->name = $name;
}
public function updateEmail(string $newEmail) {
// Validation logic here
$this->email = $newEmail; // OK: write inside class
}
}
$user = new User("123", "user@example.com", "Alice");
echo $user->id . "\n"; // OK: public read - 123
echo $user->email . "\n"; // OK: public read - user@example.com
$user->name = "Bob"; // OK: public write (symmetric visibility)
// $user->id = "456"; // Error: Cannot modify private property
// $user->email = "new@example.com"; // Error: Cannot modify private property
$user->updateEmail("new@example.com"); // OK: write through method
echo $user->email . "\n"; // new@example.com
// Example 2: Public read, protected write - inheritance pattern
class Counter {
public protected(set) int $count = 0;
public protected(set) int $maxValue = 100;
public function getValue(): int {
return $this->count;
}
}
class ResettableCounter extends Counter {
public function increment() {
if ($this->count < $this->maxValue) {
$this->count++; // OK: protected write in subclass
}
}
public function reset() {
$this->count = 0; // OK: protected write in subclass
}
}
$counter = new ResettableCounter();
echo $counter->count . "\n"; // OK: public read - 0
echo $counter->maxValue . "\n"; // OK: public read - 100
$counter->increment();
$counter->increment();
echo $counter->count . "\n"; // OK: public read - 2
// $counter->count = 10; // Error: Cannot modify protected property
// $counter->maxValue = 200; // Error: Cannot modify protected property
$counter->reset();
echo $counter->count . "\n"; // OK: public read - 0
// Example 3: Immutable value objects
readonly class Point {
public function __construct(
public private(set) float $x,
public private(set) float $y
) {}
public function distanceFrom(Point $other): float {
$dx = $this->x - $other->x;
$dy = $this->y - $other->y;
return sqrt($dx * $dx + $dy * $dy);
}
}
$p1 = new Point(0.0, 0.0);
$p2 = new Point(3.0, 4.0);
echo "P1: (" . $p1->x . ", " . $p1->y . ")\n"; // P1: (0, 0)
echo "P2: (" . $p2->x . ", " . $p2->y . ")\n"; // P2: (3, 4)
echo "Distance: " . $p1->distanceFrom($p2) . "\n"; // Distance: 5
// $p1->x = 1.0; // Error: Cannot modify private property
// $p1->y = 1.0; // Error: Cannot modify private property
// Example 4: Static properties with asymmetric visibility
class AppConfig {
public private(set) static string $environment = "development";
public private(set) static bool $debug = true;
public private(set) static array $settings = [];
public static function initialize(string $env) {
self::$environment = $env; // OK: write inside class
self::$debug = ($env === "development");
self::$settings = [
"timeout" => 30,
"retries" => 3
];
}
public static function setSetting(string $key, $value) {
self::$settings[$key] = $value; // OK: write inside class
}
}
// Public read access
echo "Environment: " . AppConfig::$environment . "\n"; // development
echo "Debug: " . (AppConfig::$debug ? "on" : "off") . "\n"; // on
// AppConfig::$environment = "production"; // Error: Cannot modify private property
// AppConfig::$debug = false; // Error: Cannot modify private property
// Must use method to modify
AppConfig::initialize("production");
echo "Environment: " . AppConfig::$environment . "\n"; // production
echo "Debug: " . (AppConfig::$debug ? "on" : "off") . "\n"; // off
// Example 5: Protected read, private write
class Authenticator {
protected private(set) string $token = "";
protected private(set) bool $authenticated = false;
private function setToken(string $token) {
$this->token = $token; // OK: private write inside class
$this->authenticated = true;
}
public function login(string $username, string $password): bool {
// Authentication logic here
if ($username === "admin" && $password === "secret") {
$this->setToken("token_" . uniqid());
return true;
}
return false;
}
public function isAuthenticated(): bool {
return $this->authenticated;
}
}
class ExtendedAuthenticator extends Authenticator {
public function getAuthStatus(): string {
// OK: protected read in subclass
if ($this->authenticated) {
return "Authenticated with token: " . substr($this->token, 0, 10) . "...";
}
return "Not authenticated";
}
public function forceLogout() {
// $this->authenticated = false; // Error: Cannot modify private property
// $this->token = ""; // Error: Cannot modify private property
// Must use public interface
}
}
$auth = new ExtendedAuthenticator();
echo $auth->getAuthStatus() . "\n"; // Not authenticated
if ($auth->login("admin", "secret")) {
echo $auth->getAuthStatus() . "\n"; // Authenticated with token: token_...
}
// Example 6: Practical use case - Event sourcing
class Event {
public private(set) string $id;
public private(set) string $type;
public private(set) array $data;
public private(set) int $timestamp;
public function __construct(string $type, array $data) {
$this->id = uniqid("evt_", true);
$this->type = $type;
$this->data = $data;
$this->timestamp = time();
}
public function toArray(): array {
return [
"id" => $this->id,
"type" => $this->type,
"data" => $this->data,
"timestamp" => $this->timestamp
];
}
}
$event = new Event("user.created", ["username" => "alice", "email" => "alice@example.com"]);
// Public read access to all properties
echo "Event ID: " . $event->id . "\n";
echo "Event Type: " . $event->type . "\n";
echo "Timestamp: " . $event->timestamp . "\n";
// Cannot modify immutable event properties
// $event->id = "evt_new"; // Error: Cannot modify private property
// $event->type = "user.updated"; // Error: Cannot modify private property
// $event->timestamp = time(); // Error: Cannot modify private property
#[\Override] Attribute (PHP 8.3)
The #[\Override] attribute validates that methods actually override parent methods, catching typos and refactoring errors at class definition time.
<?php
// Example 1: Basic override validation
class Animal {
public function makeSound() {
return "...";
}
}
class Dog extends Animal {
#[\Override]
public function makeSound() {
return "Woof!";
}
}
$dog = new Dog();
echo $dog->makeSound() . "\n"; // Woof!
// Example 2: Catching typos early
class Cat extends Animal {
// Without #[\Override], this typo would be silent
public function makeSounds() { // Typo: should be makeSound
return "Meow!";
}
}
$cat = new Cat();
echo $cat->makeSound() . "\n"; // "..." (wrong - uses parent method)
// With #[\Override], the error is caught immediately
class Bird extends Animal {
#[\Override]
public function makeSounds() { // Error at class definition!
return "Tweet!";
}
}
// Error: Bird::makeSounds has #[\Override] attribute, but no matching parent method exists
// Example 3: Interface validation
interface Drawable {
public function draw();
public function erase();
}
class Circle implements Drawable {
#[\Override]
public function draw() {
return "Drawing circle";
}
#[\Override]
public function erase() {
return "Erasing circle";
}
}
$circle = new Circle();
echo $circle->draw() . "\n"; // Drawing circle
echo $circle->erase() . "\n"; // Erasing circle
// Example 4: Trait method overriding
trait Timestampable {
public function getTimestamp() {
return time();
}
}
class Post {
use Timestampable;
#[\Override]
public function getTimestamp() {
return "2024-01-01 12:00:00"; // Custom implementation
}
}
$post = new Post();
echo $post->getTimestamp() . "\n"; // 2024-01-01 12:00:00
// Example 5: Abstract method implementation
abstract class Shape {
abstract public function area();
abstract public function perimeter();
}
class Rectangle extends Shape {
private $width = 10;
private $height = 5;
#[\Override]
public function area() {
return $this->width * $this->height;
}
#[\Override]
public function perimeter() {
return 2 * ($this->width + $this->height);
}
}
$rect = new Rectangle();
echo "Area: " . $rect->area() . "\n"; // Area: 50
echo "Perimeter: " . $rect->perimeter() . "\n"; // Perimeter: 30
// Example 6: Preventing silent refactoring errors
class Payment {
public function processPayment($amount) {
echo "Processing payment: $amount\n";
}
}
class CreditCardPayment extends Payment {
#[\Override]
public function processPayment($amount) {
echo "Processing credit card payment: $amount\n";
}
}
// Later, parent class gets refactored to use "process" instead of "processPayment"
// Without #[\Override], child class method would silently stop being called
// With #[\Override], you get an immediate error telling you to update the child class
$payment = new CreditCardPayment();
$payment->processPayment(100); // Processing credit card payment: 100
// Example 7: Multiple inheritance levels
class Vehicle {
public function start() {
return "Starting vehicle";
}
}
class Car extends Vehicle {
// Doesn't override start()
}
class SportsCar extends Car {
#[\Override]
public function start() {
return "Starting sports car with turbo!"; // Valid: overrides Vehicle::start()
}
}
$car = new SportsCar();
echo $car->start() . "\n"; // Starting sports car with turbo!
// Example 8: Magic method overrides
class Logger {
public function __toString() {
return "Logger instance";
}
}
class FileLogger extends Logger {
private $filename = "app.log";
#[\Override]
public function __toString() {
return "FileLogger: " . $this->filename;
}
}
$logger = new FileLogger();
echo $logger . "\n"; // FileLogger: app.log
VHP