Package Documentation
Introduction to Package Documentation
Good documentation is crucial for package adoption and user success. This guide covers creating comprehensive documentation including API reference, user guides, tutorials, and maintaining documentation consistency.
Documentation Types
API Documentation
Auto-generated reference documentation from code comments using tools like phpDocumentor.
User Guides
Step-by-step instructions for common use cases and getting started.
Tutorials
In-depth examples and walkthroughs for complex scenarios.
Reference Material
Quick lookup guides for functions, classes, and configuration options.
PHPDoc Standards
Basic DocBlock Structure
<?php
/**
* Brief description of the class
*
* Longer description that provides more details about the purpose
* and usage of this class. Can span multiple lines.
*
* @package Vendor\PackageName
* @version 1.2.0
* @author Your Name <[email protected]>
* @copyright 2023 Your Company
* @license MIT
* @since 1.0.0
*/
class Calculator
{
/**
* Adds two numbers together
*
* This method performs basic addition of two numeric values.
* It supports both integers and floating-point numbers.
*
* @param float $a The first number
* @param float $b The second number
* @return float The sum of the two numbers
* @throws InvalidArgumentException When either parameter is not numeric
* @since 1.0.0
* @example
* ```php
* $calculator = new Calculator();
* $result = $calculator->add(2.5, 3.7);
* echo $result; // 6.2
* ```
*/
public function add(float $a, float $b): float
{
return $a + $b;
}
/**
* Divides one number by another
*
* @param float $dividend The number to be divided
* @param float $divisor The number to divide by
* @return float The quotient
* @throws InvalidArgumentException When divisor is zero
* @throws DivisionByZeroException When attempting division by zero
* @see Calculator::multiply() For the inverse operation
* @link https://example.com/docs/calculator For more examples
* @todo Add support for integer division
* @deprecated 2.0.0 Use MathCalculator::divide() instead
*/
public function divide(float $dividend, float $divisor): float
{
if ($divisor === 0.0) {
throw new InvalidArgumentException('Division by zero is not allowed');
}
return $dividend / $divisor;
}
}
?>
Advanced DocBlock Features
<?php
/**
* Configuration manager for the calculator package
*
* @package Vendor\PackageName\Config
*/
class Configuration
{
/**
* Configuration values
*
* @var array<string, mixed>
*/
private array $config;
/**
* Default configuration values
*
* @var array{
* precision: int,
* rounding_mode: int,
* cache_enabled: bool,
* cache_ttl: int
* }
*/
private const DEFAULTS = [
'precision' => 2,
'rounding_mode' => PHP_ROUND_HALF_UP,
'cache_enabled' => true,
'cache_ttl' => 3600
];
/**
* Creates a new configuration instance
*
* @param array<string, mixed> $config Initial configuration values
*/
public function __construct(array $config = [])
{
$this->config = array_merge(self::DEFAULTS, $config);
}
/**
* Gets a configuration value
*
* @template T
* @param string $key The configuration key
* @param T $default Default value if key doesn't exist
* @return T|mixed The configuration value or default
*/
public function get(string $key, $default = null)
{
return $this->config[$key] ?? $default;
}
/**
* Batch update multiple configuration values
*
* @param array<string, mixed> $values Key-value pairs to update
* @return self Returns self for method chaining
* @fluent
*/
public function update(array $values): self
{
foreach ($values as $key => $value) {
$this->config[$key] = $value;
}
return $this;
}
}
/**
* Factory for creating calculators
*/
class CalculatorFactory
{
/**
* Creates calculator instances
*
* @param string $type Calculator type ('basic'|'scientific'|'financial')
* @param Configuration|null $config Optional configuration
* @return Calculator|ScientificCalculator|FinancialCalculator
* @throws InvalidArgumentException For unknown calculator types
* @psalm-return Calculator
*/
public static function create(string $type, ?Configuration $config = null)
{
switch ($type) {
case 'basic':
return new Calculator($config);
case 'scientific':
return new ScientificCalculator($config);
case 'financial':
return new FinancialCalculator($config);
default:
throw new InvalidArgumentException("Unknown calculator type: {$type}");
}
}
}
?>
Documentation Generation Tools
phpDocumentor Setup
# Install phpDocumentor
composer require --dev phpdocumentor/phpdocumentor
# Create configuration file
touch phpdoc.xml
phpDocumentor Configuration
<?xml version="1.0" encoding="UTF-8" ?>
<phpdocumentor
configVersion="3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://www.phpdoc.org"
xsi:schemaLocation="https://www.phpdoc.org https://raw.githubusercontent.com/phpDocumentor/phpDocumentor/master/data/xsd/phpdoc.xsd"
>
<title>Package Name API Documentation</title>
<description>Comprehensive API documentation for the Package Name library</description>
<paths>
<output>docs/api</output>
<cache>build/phpdoc-cache</cache>
</paths>
<version number="latest">
<folder>latest</folder>
<api>
<source dsn=".">
<path>src</path>
</source>
<output>api</output>
<ignore>
<path>src/deprecated</path>
</ignore>
<extensions>
<extension>php</extension>
</extensions>
<visibility>public</visibility>
<default-package-name>Vendor\PackageName</default-package-name>
</api>
<guide>
<source dsn=".">
<path>docs/guides</path>
</source>
<output>guides</output>
</guide>
</version>
<setting name="graphs.enabled" value="true" />
<setting name="guides.enabled" value="true" />
</phpdocumentor>
Generate Documentation
# Generate API documentation
vendor/bin/phpdoc run
# Generate with custom template
vendor/bin/phpdoc run --template=responsive-twig
# Watch for changes and regenerate
vendor/bin/phpdoc run --watch
User Guide Structure
README.md Template
# Package Name
[](https://packagist.org/packages/vendor/package-name)
[](LICENSE.md)
[](https://github.com/vendor/package-name/actions)
[](https://scrutinizer-ci.com/g/vendor/package-name/code-structure)
[](https://scrutinizer-ci.com/g/vendor/package-name)
[](https://packagist.org/packages/vendor/package-name)
Brief description of what your package does and why it's useful.
## Table of Contents
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Usage](#usage)
- [API Documentation](#api-documentation)
- [Examples](#examples)
- [Testing](#testing)
- [Contributing](#contributing)
- [Security](#security)
- [Changelog](#changelog)
- [License](#license)
## Installation
Install the package via Composer:
```bash
composer require vendor/package-name
Requirements
- PHP 8.0 or higher
- ext-json
- ext-mbstring
Optional Dependencies
- ext-gd (for image processing features)
- ext-curl (for HTTP client functionality)
Quick Start
Get up and running in under 5 minutes:
<?php
require_once 'vendor/autoload.php';
use Vendor\PackageName\Calculator;
$calculator = new Calculator();
$result = $calculator->add(2, 3);
echo $result; // 5
Usage
Basic Operations
use Vendor\PackageName\Calculator;
$calculator = new Calculator();
// Basic arithmetic
$sum = $calculator->add(10, 5); // 15
$difference = $calculator->subtract(10, 5); // 5
$product = $calculator->multiply(10, 5); // 50
$quotient = $calculator->divide(10, 5); // 2
Configuration
use Vendor\PackageName\Calculator;
use Vendor\PackageName\Config\Configuration;
$config = new Configuration([
'precision' => 4,
'rounding_mode' => PHP_ROUND_HALF_UP
]);
$calculator = new Calculator($config);
$result = $calculator->divide(10, 3); // 3.3333
Advanced Features
use Vendor\PackageName\Math\Operations;
// Mathematical operations
$factorial = Operations::factorial(5); // 120
$fibonacci = Operations::fibonacci(10); // 55
$power = Operations::power(2, 8); // 256
API Documentation
Complete API documentation is available at https://vendor.github.io/package-name.
Core Classes
Calculator
- Main calculator classConfiguration
- Configuration managementOperations
- Advanced mathematical operations
Examples
Example 1: Simple Calculator
<?php
require_once 'vendor/autoload.php';
use Vendor\PackageName\Calculator;
$calculator = new Calculator();
echo "Addition: " . $calculator->add(5, 3) . "\n";
echo "Subtraction: " . $calculator->subtract(5, 3) . "\n";
echo "Multiplication: " . $calculator->multiply(5, 3) . "\n";
echo "Division: " . $calculator->divide(6, 3) . "\n";
Example 2: Scientific Calculator
<?php
use Vendor\PackageName\CalculatorFactory;
use Vendor\PackageName\Config\Configuration;
$config = new Configuration(['precision' => 6]);
$calculator = CalculatorFactory::create('scientific', $config);
$result = $calculator->logarithm(100, 10); // 2.000000
echo "log₁₀(100) = " . $result . "\n";
Example 3: Error Handling
<?php
use Vendor\PackageName\Calculator;
use Vendor\PackageName\Exceptions\CalculatorException;
$calculator = new Calculator();
try {
$result = $calculator->divide(10, 0);
} catch (CalculatorException $e) {
echo "Error: " . $e->getMessage();
}
Testing
Run the test suite:
composer test
Run tests with coverage:
composer test-coverage
Contributing
Please see CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.
Security
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
Changelog
Please see CHANGELOG.md for more information about recent changes.
License
The MIT License (MIT). Please see LICENSE.md for more information.
### Comprehensive User Guide
```markdown
# User Guide
This guide provides detailed information on using the Package Name library.
## Table of Contents
1. [Getting Started](#getting-started)
2. [Basic Concepts](#basic-concepts)
3. [Configuration](#configuration)
4. [Common Use Cases](#common-use-cases)
5. [Advanced Topics](#advanced-topics)
6. [Best Practices](#best-practices)
7. [Troubleshooting](#troubleshooting)
## Getting Started
### Installation
Before you begin, ensure you have:
- PHP 8.0 or later
- Composer installed
Install the package:
```bash
composer require vendor/package-name
Your First Calculation
<?php
require 'vendor/autoload.php';
use Vendor\PackageName\Calculator;
// Create a calculator instance
$calculator = new Calculator();
// Perform a simple calculation
$result = $calculator->add(10, 5);
echo "10 + 5 = " . $result; // 10 + 5 = 15
Basic Concepts
Calculator Class
The Calculator
class is the main entry point for performing calculations:
$calculator = new Calculator();
Operations
All basic arithmetic operations are supported:
- Addition:
add($a, $b)
- Subtraction:
subtract($a, $b)
- Multiplication:
multiply($a, $b)
- Division:
divide($a, $b)
Error Handling
The library uses exceptions for error handling:
try {
$result = $calculator->divide(10, 0);
} catch (CalculatorException $e) {
echo "Error: " . $e->getMessage();
}
Configuration
Basic Configuration
use Vendor\PackageName\Config\Configuration;
$config = new Configuration([
'precision' => 2,
'cache_enabled' => true
]);
$calculator = new Calculator($config);
Configuration Options
Option | Type | Default | Description |
---|---|---|---|
precision | int | 2 | Number of decimal places |
rounding_mode | int | PHP_ROUND_HALF_UP | Rounding mode |
cache_enabled | bool | true | Enable result caching |
cache_ttl | int | 3600 | Cache time-to-live in seconds |
Environment Configuration
Create a .env
file for environment-specific settings:
CALCULATOR_PRECISION=4
CALCULATOR_CACHE_ENABLED=true
CALCULATOR_DEBUG=false
Load environment configuration:
$config = Configuration::fromEnvironment();
$calculator = new Calculator($config);
Common Use Cases
Financial Calculations
use Vendor\PackageName\CalculatorFactory;
$calculator = CalculatorFactory::create('financial');
// Calculate compound interest
$principal = 1000;
$rate = 0.05;
$time = 10;
$compoundInterest = $calculator->compoundInterest($principal, $rate, $time);
Scientific Calculations
$scientific = CalculatorFactory::create('scientific');
// Trigonometric functions
$sine = $scientific->sin(M_PI / 2); // 1
$cosine = $scientific->cos(0); // 1
$tangent = $scientific->tan(M_PI / 4); // 1
// Logarithmic functions
$naturalLog = $scientific->ln(M_E); // 1
$log10 = $scientific->log10(100); // 2
Batch Processing
$numbers = [1, 2, 3, 4, 5];
$results = [];
foreach ($numbers as $number) {
$results[] = $calculator->multiply($number, 2);
}
// Or use array functions
$doubled = array_map(fn($n) => $calculator->multiply($n, 2), $numbers);
Advanced Topics
Custom Operations
Extend the calculator with custom operations:
class CustomCalculator extends Calculator
{
public function percentage(float $value, float $percentage): float
{
return $this->multiply($value, $this->divide($percentage, 100));
}
public function average(array $numbers): float
{
$sum = array_reduce($numbers, fn($carry, $item) => $this->add($carry, $item), 0);
return $this->divide($sum, count($numbers));
}
}
Plugins and Extensions
Load additional functionality through plugins:
use Vendor\PackageName\Plugin\StatisticsPlugin;
$calculator = new Calculator();
$calculator->loadPlugin(new StatisticsPlugin());
// Now statistical functions are available
$mean = $calculator->mean([1, 2, 3, 4, 5]);
$median = $calculator->median([1, 2, 3, 4, 5]);
Caching Results
Enable caching for expensive operations:
$config = new Configuration(['cache_enabled' => true, 'cache_ttl' => 1800]);
$calculator = new Calculator($config);
// First call calculates and caches
$result1 = $calculator->complexOperation($data);
// Second call retrieves from cache
$result2 = $calculator->complexOperation($data); // Much faster
Best Practices
Input Validation
Always validate inputs before performing calculations:
public function safeDivide(float $a, float $b): float
{
if (!is_finite($a) || !is_finite($b)) {
throw new InvalidArgumentException('Arguments must be finite numbers');
}
if ($b === 0.0) {
throw new DivisionByZeroException('Cannot divide by zero');
}
return $this->divide($a, $b);
}
Error Handling Strategy
Implement comprehensive error handling:
try {
$result = $calculator->complexCalculation($data);
} catch (CalculatorException $e) {
// Log the error
error_log("Calculation error: " . $e->getMessage());
// Provide fallback value or re-throw
return 0; // or throw $e;
} catch (Exception $e) {
// Handle unexpected errors
error_log("Unexpected error: " . $e->getMessage());
throw new CalculatorException("Calculation failed", 0, $e);
}
Performance Optimization
Optimize for performance in high-throughput scenarios:
// Reuse calculator instances
$calculator = new Calculator($config);
// Batch operations when possible
$results = $calculator->batchAdd($numbers1, $numbers2);
// Use appropriate precision
$config = new Configuration(['precision' => 2]); // Instead of 10
Troubleshooting
Common Issues
"Class not found" errors
Ensure Composer autoloader is included:
require_once 'vendor/autoload.php';
Precision issues with floating-point numbers
Use the bcmath extension for high-precision calculations:
$config = new Configuration([
'precision' => 10,
'use_bcmath' => true
]);
Memory issues with large datasets
Process data in chunks:
$chunks = array_chunk($largeDataset, 1000);
foreach ($chunks as $chunk) {
$results[] = $calculator->processChunk($chunk);
}
Debug Mode
Enable debug mode for detailed error information:
$config = new Configuration(['debug' => true]);
$calculator = new Calculator($config);
Getting Help
- Check the API documentation
- Search existing issues
- Join our community forum
- Contact support at [email protected]
## Code Examples Documentation
### Organized Examples
```php
<?php
// examples/basic-usage.php
/**
* Basic Usage Examples
*
* This file demonstrates the basic functionality of the Calculator package.
* Run with: php examples/basic-usage.php
*/
require_once __DIR__ . '/../vendor/autoload.php';
use Vendor\PackageName\Calculator;
use Vendor\PackageName\Config\Configuration;
echo "=== Basic Calculator Examples ===\n\n";
// Example 1: Simple arithmetic
echo "1. Simple Arithmetic\n";
$calculator = new Calculator();
$a = 10;
$b = 5;
echo "Adding {$a} + {$b} = " . $calculator->add($a, $b) . "\n";
echo "Subtracting {$a} - {$b} = " . $calculator->subtract($a, $b) . "\n";
echo "Multiplying {$a} * {$b} = " . $calculator->multiply($a, $b) . "\n";
echo "Dividing {$a} / {$b} = " . $calculator->divide($a, $b) . "\n\n";
// Example 2: Configuration
echo "2. Using Configuration\n";
$config = new Configuration([
'precision' => 4,
'rounding_mode' => PHP_ROUND_HALF_UP
]);
$preciseCalculator = new Calculator($config);
$result = $preciseCalculator->divide(22, 7);
echo "π approximation (22/7) with 4 decimal places: {$result}\n\n";
// Example 3: Error handling
echo "3. Error Handling\n";
try {
$calculator->divide(10, 0);
} catch (Exception $e) {
echo "Caught exception: " . $e->getMessage() . "\n";
}
echo "\nExample completed successfully!\n";
?>
Interactive Examples
<?php
// examples/interactive-calculator.php
/**
* Interactive Calculator Example
*
* A simple command-line calculator interface.
* Run with: php examples/interactive-calculator.php
*/
require_once __DIR__ . '/../vendor/autoload.php';
use Vendor\PackageName\Calculator;
use Vendor\PackageName\Exceptions\CalculatorException;
class InteractiveCalculator
{
private Calculator $calculator;
public function __construct()
{
$this->calculator = new Calculator();
}
public function run(): void
{
echo "Welcome to the Interactive Calculator!\n";
echo "Type 'help' for commands or 'quit' to exit.\n\n";
while (true) {
$input = $this->prompt("> ");
if (trim($input) === 'quit') {
echo "Goodbye!\n";
break;
}
if (trim($input) === 'help') {
$this->showHelp();
continue;
}
$this->processInput($input);
}
}
private function prompt(string $message): string
{
echo $message;
return trim(fgets(STDIN));
}
private function showHelp(): void
{
echo "Available commands:\n";
echo " add <a> <b> - Add two numbers\n";
echo " sub <a> <b> - Subtract two numbers\n";
echo " mul <a> <b> - Multiply two numbers\n";
echo " div <a> <b> - Divide two numbers\n";
echo " help - Show this help\n";
echo " quit - Exit calculator\n\n";
}
private function processInput(string $input): void
{
$parts = explode(' ', trim($input));
if (count($parts) < 3) {
echo "Error: Invalid input. Type 'help' for usage.\n";
return;
}
[$operation, $a, $b] = $parts;
if (!is_numeric($a) || !is_numeric($b)) {
echo "Error: Arguments must be numeric.\n";
return;
}
$a = (float) $a;
$b = (float) $b;
try {
$result = match ($operation) {
'add' => $this->calculator->add($a, $b),
'sub' => $this->calculator->subtract($a, $b),
'mul' => $this->calculator->multiply($a, $b),
'div' => $this->calculator->divide($a, $b),
default => throw new InvalidArgumentException("Unknown operation: {$operation}")
};
echo "Result: {$result}\n";
} catch (CalculatorException $e) {
echo "Calculator Error: " . $e->getMessage() . "\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
}
}
$calculator = new InteractiveCalculator();
$calculator->run();
?>
Documentation Automation
GitHub Actions for Documentation
# .github/workflows/docs.yml
name: Documentation
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
generate-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
extensions: dom, curl, libxml, mbstring, zip
- name: Install dependencies
run: composer install --no-dev --optimize-autoloader
- name: Generate API documentation
run: vendor/bin/phpdoc run
- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/api
publish_branch: gh-pages
Documentation Validation
<?php
// scripts/validate-docs.php
/**
* Documentation validation script
* Ensures all public methods have proper documentation
*/
class DocumentationValidator
{
private array $errors = [];
public function validateDirectory(string $path): bool
{
$files = glob($path . '/*.php');
foreach ($files as $file) {
$this->validateFile($file);
}
return empty($this->errors);
}
private function validateFile(string $file): void
{
$content = file_get_contents($file);
$tokens = token_get_all($content);
for ($i = 0; $i < count($tokens); $i++) {
if ($this->isPublicMethod($tokens, $i)) {
$methodName = $this->getMethodName($tokens, $i);
if (!$this->hasDocBlock($tokens, $i)) {
$this->errors[] = "Missing DocBlock for method {$methodName} in {$file}";
}
}
}
}
private function isPublicMethod(array $tokens, int $index): bool
{
// Look for 'public function' pattern
return isset($tokens[$index]) &&
is_array($tokens[$index]) &&
$tokens[$index][0] === T_PUBLIC &&
isset($tokens[$index + 2]) &&
is_array($tokens[$index + 2]) &&
$tokens[$index + 2][0] === T_FUNCTION;
}
private function getMethodName(array $tokens, int $index): string
{
// Find method name after 'function' keyword
for ($i = $index; $i < count($tokens); $i++) {
if (is_array($tokens[$i]) && $tokens[$i][0] === T_STRING) {
return $tokens[$i][1];
}
}
return 'unknown';
}
private function hasDocBlock(array $tokens, int $index): bool
{
// Look backwards for DocBlock comment
for ($i = $index - 1; $i >= 0; $i--) {
if (is_array($tokens[$i]) && $tokens[$i][0] === T_DOC_COMMENT) {
return true;
}
// Stop at previous method or class
if (is_array($tokens[$i]) &&
in_array($tokens[$i][0], [T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT])) {
break;
}
}
return false;
}
public function getErrors(): array
{
return $this->errors;
}
}
$validator = new DocumentationValidator();
$isValid = $validator->validateDirectory('src');
if (!$isValid) {
echo "Documentation validation failed:\n";
foreach ($validator->getErrors() as $error) {
echo "- {$error}\n";
}
exit(1);
}
echo "Documentation validation passed!\n";
?>
Comprehensive documentation is essential for package adoption and maintainability. It serves as both a reference for users and a guide for contributors, ensuring your package can be effectively used and maintained over time.