Compare commits

...

10 Commits

Author SHA1 Message Date
Ramon Caballero c750d4014b Merge branch 'task/setup' 2026-04-10 11:56:44 +01:00
Ramon Caballero 2e43626d91 Add README.md 2026-04-10 11:56:29 +01:00
Ramon Caballero d80970c452 Introduce project path constants for cleaner initialization 2026-04-10 11:51:41 +01:00
Ramon Caballero d3ba8eedfe Enable strict typing across the codebase and tests 2026-04-10 11:51:41 +01:00
Ramon Caballero 38304ed045 Load environment variables and establish database connection 2026-04-10 11:51:41 +01:00
Ramon Caballero 6918931ecc Add phpdotenv for environment variable management 2026-04-10 11:51:41 +01:00
Ramon Caballero 4b23dfd18b Add PHP CS Fixer for consistent code style 2026-04-10 11:51:41 +01:00
Ramon Caballero ba5a8dc8ea Add PHPUnit for testing 2026-04-10 11:51:41 +01:00
Ramon Caballero 732b0c7e0c Initialize Composer and PSR‑4 autoloading 2026-04-10 11:51:41 +01:00
Ramon Caballero 61497e79b3 Add placeholder application files 2026-04-10 11:51:38 +01:00
18 changed files with 4834 additions and 0 deletions

13
.gitignore vendored
View File

@ -3,3 +3,16 @@
# Runtime / writable directories:
var/
# Environment variables:
*.env
# Composer dependencies:
/vendor/
# PHPUnit caches:
.phpunit.cache/
.phpunit.result.cache
# PHP CS Fixer caches:
.php-cs-fixer.cache

34
.php-cs-fixer.dist.php Normal file
View File

@ -0,0 +1,34 @@
<?php
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
$finder = Finder::create()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
->in(__DIR__ . '/public')
->in(__DIR__ . '/config')
->exclude('vendor')
->name('*.php')
->ignoreDotFiles(true)
->ignoreVCS(true);
return (new Config())
->setIndent("\t")
->setRiskyAllowed(true)
->setRules([
'@PSR12' => true,
'array_syntax' => ['syntax' => 'short'],
'blank_line_before_statement' => ['statements' => ['return', 'throw', 'break', 'continue', 'exit']],
'braces_position' => ['control_structures_opening_brace' => 'next_line_unless_newline_at_signature_end'],
'control_structure_continuation_position' => ['position' => 'next_line'],
'indentation_type' => true,
'no_extra_blank_lines' => true,
'no_trailing_whitespace' => true,
'no_unused_imports' => true,
'ordered_imports' => true,
'single_blank_line_at_eof' => true,
'single_import_per_statement' => true,
'trailing_comma_in_multiline' => ['elements' => ['arrays', 'arguments']],
])
->setFinder($finder);

111
README.md Normal file
View File

@ -0,0 +1,111 @@
# PHPStarter
A minimal, modern PHP project template that provides a clean foundation for building small to medium web applications.
## Features
- PSR4 autoloading via Composer
- Environment configuration using [`vlucas/phpdotenv`](https://github.com/vlucas/phpdotenv)
- Strict typing enabled across the project
- Simple and extensible database connection helper
- Readytouse [PHPUnit](https://phpunit.de/) testing setup
- [PHPCSFixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) configuration for consistent code style
- Clean `public/` entry point for web requests
- Fully compatible with the [PHPStarter CLI](https://ramoncaballero.dev/phpstarter-cli.git)
## Requirements
- PHP 8.2+
- Composer
- Apache (or PHP's builtin server)
- MariaDB
## Installation
It is recommended to use [PHPStarter CLI](https://ramoncaballero.dev/phpstarter-cli.git), as it automates the entire setup process and requires almost no manual configuration.
However, you can also install PHPStarter manually by following the steps below.
Clone the repository:
```bash
cd /var/www/sites/
git clone https://ramoncaballero.dev/PHPStarter.git <myproject>
cd <myproject>
```
Install dependencies:
```bash
composer install
```
Copy the environment file:
```bash
sudo cp config/PHPStarter.env.example config/PHPStarter.env
```
Edit your environment variables as needed.
## Directory Structure
```bash
PHPStarter/
bin/ → Executable scripts or CLI utilities
config/ → Environment files
docs/ → Project documentation, guides, and reference material
public/ → Web root; front controller (`index.php`) and public assets (css, js, icons, ...)
src/ → Application source code (PSR4 autoloaded)
templates/ → Reusable HTML/PHP templates or view files
tests/ → PHPUnit test suites and testing utilities
translations/ → Localization files, language packs, or message catalogs
composer.json → Composer package definition and autoload configuration
composer.lock → Locked dependency versions for reproducible installs
phpunit.xml → PHPUnit configuration file
.php-cs-fixer.dist.php → Code style rules for PHP-CS-Fixer
```
## Running the Project
Using PHP's builtin server:
```bash
php -S localhost:8000 -t public
```
Or configure Apache manually.
If using the [PHPStarter CLI](https://ramoncaballero.dev/phpstarter-cli.git), the virtual host is created automatically.
## Customization
You can safely modify:
- Namespace (default: `PHPStarter`)
- Directory structure
- Database logic
- Views/templates
The template is intentionally minimal to encourage flexibility.
## Testing
Run PHPUnit:
```bash
./vendor/bin/phpunit
```
## Code Style
Run PHP-CS-Fixer:
```bash
./vendor/bin/php-cs-fixer fix
```
## License
This project is provided as a template and may be used freely.

22
composer.json Normal file
View File

@ -0,0 +1,22 @@
{
"name": "ramoncaballero.dev/phpstarter",
"description": "PHPStarter",
"authors": [
{
"name": "Ramon Caballero",
"email": "hello@ramoncaballero.dev"
}
],
"autoload": {
"psr-4": {
"PHPStarter\\": "src/"
}
},
"require-dev": {
"phpunit/phpunit": "^12.5",
"friendsofphp/php-cs-fixer": "^3.94"
},
"require": {
"vlucas/phpdotenv": "^5.6"
}
}

4512
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
DB_HOST=127.0.0.1
DB_NAME=PHPStarter
DB_PORT=3306
DB_SOCKET=/var/run/mysqld/mysqld10.sock
DB_USER=PHPStarter_user
DB_PASS=PHPStarter_user_password

43
config/database.sql Normal file
View File

@ -0,0 +1,43 @@
--
-- Create database
--
DROP DATABASE IF EXISTS `PHPStarter`;
CREATE DATABASE IF NOT EXISTS `PHPStarter`;
USE `PHPStarter`;
--
-- Create user for database
--
DROP USER IF EXISTS 'PHPStarter_user'@'localhost';
CREATE USER 'PHPStarter_user'@'localhost' IDENTIFIED BY '';
GRANT ALL PRIVILEGES ON `PHPStarter`.* TO 'PHPStarter_user'@'localhost';
FLUSH PRIVILEGES;
--
-- Drop tables
--
DROP TABLE IF EXISTS `PHPStarter`;
--
-- Table structure for 'PHPStarter'
--
CREATE TABLE `PHPStarter` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`message` VARCHAR(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Reset 'PHPStarter'
--
DELETE FROM `PHPStarter`;
ALTER TABLE `PHPStarter` AUTO_INCREMENT = 1;
INSERT INTO `PHPStarter` (`message`) VALUES
("Welcome to PHPStarter");

10
phpunit.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.4/phpunit.xsd"
bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="PHPStarter Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>

39
public/index.php Normal file
View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
define('PROJECT_ROOT', dirname(__DIR__));
define('CONFIG_DIRECTORY', PROJECT_ROOT . '/config/');
require_once PROJECT_ROOT . '/vendor/autoload.php';
use Dotenv\Dotenv;
$dotenv = Dotenv::createImmutable(CONFIG_DIRECTORY, 'PHPStarter.env');
$dotenv->load();
use PHPStarter\DB;
$pdo = DB::connect();
$query = "SELECT * FROM `PHPStarter` WHERE `id` = 1";
$stmt = $pdo->prepare($query);
$stmt->execute();
$PHPStarter = $stmt->fetch();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><?= $PHPStarter->message ?></title>
<link rel="stylesheet" type="text/css" href="./css/PHPStarter.css">
<link rel="icon" type="image/x-icon" href="./icons/favicon.ico">
</head>
<body>
<h1><?= $PHPStarter->message ?></h1>
<script type="text/javascript" src="./js/PHPStarter.js"></script>
</body>
</html>

View File

View File

26
src/DB.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace PHPStarter;
use PDO;
use PDOException;
class DB
{
public static function connect(): PDO
{
try
{
$dsn = "mysql:host={$_ENV['DB_HOST']};dbname={$_ENV['DB_NAME']};port={$_ENV['DB_PORT']};unix_socket={$_ENV['DB_SOCKET']}";
$pdo = new PDO($dsn, $_ENV['DB_USER'], $_ENV['DB_PASS']);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $exception)
{
die("Database connection failed: " . $exception->getMessage());
}
return $pdo;
}
}

View File

11
tests/ExampleTest.php Normal file
View File

@ -0,0 +1,11 @@
<?php
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
public function test_it_works()
{
$this->assertTrue(true);
}
}

7
tests/bootstrap.php Normal file
View File

@ -0,0 +1,7 @@
<?php
declare(strict_types=1);
define('PROJECT_ROOT', dirname(__DIR__));
require_once PROJECT_ROOT . '/vendor/autoload.php';