MyBlog Developer Setup Guide
Overview
This guide helps developers set up the MyBlog project for development and contribution.
Requirements
- PHP 8.0 or higher
- Composer 2.0 or higher
- Git (for version control)
- A web server (Apache, Nginx, or PHP built-in server)
Installation
1. Clone Repository
git clone <repository-url> myblog
cd myblog
2. Install Dependencies
composer install
This installs:
- PHPUnit (testing framework)
- PHPStan (static analysis)
- PHPCS (code style checking)
- PHP CS Fixer (code style fixing)
3. Configure Blog
Edit _blog/config.php:
<?php
// Blog Configuration
define('BLOG_TITLE', 'My Blog');
define('BLOG_DESCRIPTION', 'A simple blog powered by PHP & Markdown');
define('BLOG_AUTHOR', 'Your Name');
// Base paths
define('BLOG_ROOT', __DIR__);
4. Setup Web Server
Option A: PHP Built-in Server (Development Only)
php -S localhost:8000
Visit http://localhost:8000
Option B: Apache
Create virtual host:
<VirtualHost *:80>
ServerName myblog.local
DocumentRoot /path/to/myblog
<Directory /path/to/myblog>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Add to /etc/hosts:
127.0.0.1 myblog.local
Option C: Nginx
server {
listen 80;
server_name myblog.local;
root /path/to/myblog;
index index.php index.html;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
Project Structure
myblog/
├── _blog/
│ ├── src/
│ │ ├── Renderer/
│ │ │ ├── BlogRenderer.php
│ │ │ └── BlogContentProcessor.php
│ │ ├── Parser/
│ │ │ └── Parsedown.php
│ │ └── Security/
│ │ ├── SecurityFilter.php
│ │ ├── CSRFProtection.php
│ │ ├── InputValidator.php
│ │ └── PathValidator.php
│ ├── helpers/
│ │ └── helpers.php
│ ├── config.php
│ ├── template_article.php
│ ├── template_index.php
│ └── style.css
├── tests/
│ ├── Unit/
│ │ └── Blog/
│ │ └── Renderer/
│ │ ├── BlogRendererTest.php
│ │ └── BlogContentProcessorTest.php
│ ├── Integration/
│ │ └── RenderFlowTest.php
│ ├── SecurityTest.php
│ ├── CSRFProtectionTest.php
│ ├── InputValidatorTest.php
│ └── PathValidatorTest.php
├── docs/
│ └── api/
│ ├── BlogRenderer.md
│ ├── BlogContentProcessor.md
│ └── Security.md
├── composer.json
├── phpunit.xml
└── .php-cs-fixer.php
Development Workflow
Running Tests
Run all tests:
composer test
Run specific test suite:
vendor/bin/phpunit tests/Unit
vendor/bin/phpunit tests/Integration
vendor/bin/phpunit tests/SecurityTest.php
Run with testdox output:
vendor/bin/phpunit --testdox
Code Style
Check code style:
composer cs-check
Auto-fix code style:
composer cs-fix
Static Analysis
Run PHPStan:
composer phpstan
Test Coverage
Generate coverage report:
composer test:coverage
View report in coverage/html/index.html
Creating Blog Posts
1. Create Markdown File
Create a .md file in any directory:
---
title: My First Post
description: An introduction to my blog
---
# My First Post
This is my first blog post written in Markdown.
## Features
- **Bold** and *italic* text
- Code blocks:
```php
echo "Hello, World!";
```
- Math: $E = mc^2$
- Tables:
| Name | Age |
|------|-----|
| John | 25 |
2. Access Post
Navigate to the directory in your browser:
http://localhost:8000/directory/post.html
The blog automatically generates HTML from Markdown files.
Writing Tests
Unit Tests
Create test class in tests/Unit/:
<?php
declare(strict_types=1);
namespace Tests\Unit\Blog\YourNamespace;
use PHPUnit\Framework\TestCase;
use Blog\YourNamespace\YourClass;
class YourClassTest extends TestCase
{
private YourClass $instance;
protected function setUp(): void
{
$this->instance = new YourClass();
}
public function testSomething(): void
{
$result = $this->instance->doSomething();
$this->assertEquals('expected', $result);
}
}
Integration Tests
Create test class in tests/Integration/:
<?php
declare(strict_types=1);
namespace Tests\Integration;
use PHPUnit\Framework\TestCase;
use Blog\Renderer\BlogContentProcessor;
class RenderFlowTest extends TestCase
{
public function testCompleteRenderFlow(): void
{
$processor = new BlogContentProcessor();
$result = $processor->processMarkdownFile('test.md');
$this->assertIsArray($result);
$this->assertArrayHasKey('title', $result);
$this->assertArrayHasKey('content', $result);
}
}
Running Tests
vendor/bin/phpunit tests/Unit/Blog/Renderer
vendor/bin/phpunit tests/Integration
Code Style
PSR-12 Compliance
All code must follow PSR-12 coding standards.
Pre-commit Hook
The project includes a Git pre-commit hook for code style checking:
# Automatically runs before each commit
.git/hooks/pre-commit
To manually check:
composer cs-check
To auto-fix issues:
composer cs-fix
Common Issues
Issue: Missing docblocks
composer cs-fix
# Manually add required docblocks
Issue: Trailing whitespace
composer cs-fix
Issue: Line length > 120
// Bad
$veryLongVariableName = someFunctionWithVeryLongName(parameter1, parameter2, parameter3);
// Good
$veryLongVariableName = someFunctionWithVeryLongName(
parameter1,
parameter2,
parameter3
);
Using the Blog Classes
BlogRenderer
<?php
require 'vendor/autoload.php';
use Blog\Renderer\BlogRenderer;
$renderer = new BlogRenderer();
// Configure
$renderer->setConfig([
'title' => 'My Blog',
'description' => 'Tech articles',
]);
// Parse Markdown
$html = $renderer->parseMarkdown('# Hello');
// Render document
echo $renderer->renderDocument([
'title' => 'Post Title',
'content' => $html,
'toc' => []
]);
BlogContentProcessor
<?php
use Blog\Renderer\BlogContentProcessor;
$processor = new BlogContentProcessor();
$result = $processor->processMarkdownFile('post.md');
// $result contains:
// - ['title' => 'Post Title']
// - ['content' => '<h1>...</h1>']
// - ['toc' => [...]]
Security Classes
<?php
use Blog\Security\SecurityFilter;
use Blog\Security\InputValidator;
use Blog\Security\CSRFProtection;
// XSS Protection
echo SecurityFilter::escapeHtml($userInput);
// Input Validation
$email = $_POST['email'] ?? '';
if (!InputValidator::validateEmail($email)) {
die('Invalid email');
}
// CSRF Protection
$csrf = new CSRFProtection();
echo $csrf->getHiddenField(); // In form
$csrf->validateRequestOnce(); // On submit
Troubleshooting
Composer Install Fails
Issue: Permission denied
# Fix ownership
sudo chown -R $USER:$USER ~/.composer
sudo chown -R $USER:$USER vendor
PHPUnit Errors
Issue: Class not found
# Regenerate autoload
composer dump-autoload
Issue: Test fails
# Run specific test with verbose output
vendor/bin/phpunit --testdox --verbose tests/YourTest.php
PHPStan Errors
Issue: Undefined variable
// Bad
echo $variable;
// Good
$variable = 'value';
echo $variable;
Code Style Issues
Issue: Pre-commit hook fails
# Fix issues
composer cs-fix
# Or commit with --no-verify (not recommended)
git commit --no-verify
Contributing
Pull Request Process
- Fork the repository
- Create feature branch:
``bash
git checkout -b feature/your-feature
``
- Make changes
- Run tests:
``bash
composer test
composer cs-check
composer phpstan
``
- Commit changes:
``bash
git commit -m "Add feature"
``
- Push to fork:
``bash
git push origin feature/your-feature
``
- Create pull request
Commit Message Format
Follow conventional commits:
feat: add new feature
fix: resolve issue #123
docs: update documentation
test: add tests for BlogRenderer
refactor: improve code structure
style: fix code style issues
chore: update dependencies
Code Review Checklist
- [ ] All tests pass
- [ ] Code follows PSR-12
- [ ] No PHPStan errors
- [ ] Documentation updated
- [ ] Commit messages clear
Useful Commands
# Run all tests
composer test
# Check code style
composer cs-check
# Fix code style
composer cs-fix
# Run static analysis
composer phpstan
# Generate coverage
composer test:coverage
# Update dependencies
composer update
# Install dependencies
composer install
# Regenerate autoload
composer dump-autoload
Support
- Documentation: See
docs/api/for API documentation - Issues: Report bugs via GitHub Issues
- Tests: Check test files in
tests/for usage examples