Skip to content

Шаблон для создания новых приложений на кастомном PHP фреймворке

License

Notifications You must be signed in to change notification settings

sedalit/simple-php-framework-skeleton

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Simple PHP Framework - Шаблон приложения

Версия PHP Framework Лицензия

Шаблон приложения для Simple PHP Framework.

🚀 Быстрый старт

Создание нового проекта

composer create-project sedalit/simple-php-framework-skeleton my-app
cd my-app

Настройка окружения

# Скопируйте файл окружения
cp .env.example .env

# Отредактируйте .env
nano .env

Настройте базу данных и другие параметры:

# База данных
DB_HOST="localhost"
DB_NAME="your_database"
DB_USERNAME="your_username"
DB_PASSWORD="your_password"
DB_CHARSET="utf8mb4"

# Приложение
APP_NAME="Мое приложение"
APP_URL="http://localhost:8000"
APP_DEBUG=true

# Почта (опционально)
MAIL_HOST="smtp.example.com"
MAIL_USERNAME="your@email.com"
MAIL_PASSWORD="your_password"
MAIL_PORT="465"

Настройка веб-сервера

Сервер разработки (встроенный PHP)

php -S localhost:8000 -t public

Откройте http://localhost:8000 в браузере!

Конфигурация Apache

Укажите DocumentRoot на директорию public:

<VirtualHost *:80>
    ServerName myapp.local
    DocumentRoot /path/to/my-app/public
    
    <Directory /path/to/my-app/public>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Конфигурация Nginx

server {
    listen 80;
    server_name myapp.local;
    root /path/to/my-app/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    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;
    }
}

📁 Структура проекта

my-app/
├── app/
│   ├── Controllers/           # Контроллеры приложения
│   │   ├── BaseController.php
│   │   └── IndexController.php
│   ├── Models/               # Модели данных
│   ├── Views/                # Шаблоны представлений
│   │   ├── layouts/          # Шаблоны макетов
│   │   │   └── default.php
│   │   ├── includes/         # Переиспользуемые компоненты
│   │   ├── error.php         # Страница ошибки
│   │   └── index.php         # Главная страница
│   ├── Middlewares/          # Пользовательские middleware
│   └── Validation/
│       └── Rules/            # Пользовательские правила валидации
├── config/
│   ├── init.php              # Конфигурация приложения
│   ├── db.php                # Конфигурация базы данных
│   ├── mail.php              # Конфигурация почты
│   ├── routes.php            # Определение маршрутов
│   └── serviceProviders.php  # Сервис-провайдеры
├── public/                   # Публичная веб-директория
│   ├── index.php             # Точка входа приложения
│   ├── .htaccess             # Правила перезаписи Apache
│   └── assets/               # Статические ресурсы
│       ├── css/
│       ├── js/
│       └── images/
├── tmp/
│   └── cache/                # Кеш приложения
├── uploads/                  # Загруженные пользователями файлы
├── tests/                    # Тесты приложения
├── vendor/                   # Зависимости Composer
├── bin/
│   └── console               # CLI инструмент
├── .env                      # Переменные окружения (создайте из .env.example)
├── .env.example              # Шаблон окружения
├── .gitignore
├── composer.json
└── README.md

🎯 Разработка приложения

1. Определение маршрутов

Отредактируйте config/routes.php:

<?php

use App\Controllers\IndexController;
use App\Controllers\PostController;
use PHPFramework\Middlewares\AuthMiddleware;

// Главная страница
$app->router()->get('/', [IndexController::class, 'index']);

// Статьи
$app->router()->get('/posts', [PostController::class, 'index']);
$app->router()->get('/posts/(?<id>\d+)', [PostController::class, 'show']);
$app->router()->post('/posts', [PostController::class, 'store'], [AuthMiddleware::class]);

// Админ-панель
$app->router()->group('/admin', [
    $app->router()->get('/dashboard', [AdminController::class, 'index']),
    $app->router()->get('/users', [AdminController::class, 'users']),
])->middleware([AuthMiddleware::class]);

2. Создание контроллера

php bin/console make:controller PostController

Это создаст app/Controllers/PostController.php:

<?php

namespace App\Controllers;

class PostController extends BaseController 
{
    public function index(): mixed
    {
        $posts = db()->table('posts')
            ->where('status', 'published')
            ->orderBy('created_at', 'DESC')
            ->get();
        
        return $this->render('posts/index', [
            'title' => 'Все статьи',
            'posts' => $posts
        ]);
    }
    
    public function show(): mixed
    {
        $id = router()->routeParam('id');
        
        $post = db()->table('posts')
            ->where('id', $id)
            ->first();
        
        if (!$post) {
            abort('Статья не найдена', 404);
        }
        
        return $this->render('posts/show', ['post' => $post]);
    }
    
    public function store(): mixed
    {
        $data = request()->post();
        
        // Валидация
        if (!validate($data, [
            'title' => 'required|min:3|max:200',
            'content' => 'required|min:10'
        ])) {
            return response()->redirect('/posts/create')
                ->send();
        }
        
        // Сохранение
        $id = db()->table('posts')->insert([
            'title' => $data['title'],
            'content' => $data['content'],
            'user_id' => session()->get('user_id'),
            'created_at' => date('Y-m-d H:i:s')
        ]);
        
        session()->setFlash('success', 'Статья успешно создана!');
        return response()->redirect("/posts/{$id}")->send();
    }
}

3. Создание модели

php bin/console make:model Post

Это создаст app/Models/Post.php:

<?php

namespace App\Models;

use PHPFramework\Model;

class Post extends Model 
{
    protected array $fillable = ['title', 'content', 'user_id', 'status'];
    
    protected function tableName(): string 
    {
        return 'posts';
    }
    
    protected function primaryKeyName(): string 
    {
        return 'id';
    }
}

4. Создание представлений

Создайте app/Views/posts/index.php:

<div class="container mt-4">
    <h1><?= h($title) ?></h1>
    
    <?php if (empty($posts)): ?>
        <p>Статьи не найдены.</p>
    <?php else: ?>
        <div class="row">
            <?php foreach($posts as $post): ?>
                <div class="col-md-6 mb-4">
                    <div class="card">
                        <div class="card-body">
                            <h5 class="card-title">
                                <a href="<?= baseUrl("/posts/{$post['id']}") ?>">
                                    <?= h($post['title']) ?>
                                </a>
                            </h5>
                            <p class="card-text">
                                <?= h(substr($post['content'], 0, 150)) ?>...
                            </p>
                            <small class="text-muted">
                                <?= date('d.m.Y', strtotime($post['created_at'])) ?>
                            </small>
                        </div>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
    <?php endif; ?>
</div>

5. Создание пользовательского Middleware

php bin/console make:middleware AdminMiddleware

Отредактируйте app/Middlewares/AdminMiddleware.php:

<?php

namespace App\Middlewares;

use PHPFramework\Interfaces\MiddlewareInterface;
use PHPFramework\Request;
use PHPFramework\Response;

class AdminMiddleware implements MiddlewareInterface 
{
    public function handle(Request $request, Response $response, callable $next): mixed
    {
        $user = session()->get('user');
        
        if (!$user || $user['role'] !== 'admin') {
            abort('Доступ запрещен', 403);
        }
        
        return $next();
    }
}

6. Создание пользовательского правила валидации

php bin/console make:rule PhoneRule

Отредактируйте app/Validation/Rules/PhoneRule.php:

<?php

namespace App\Validation\Rules;

use PHPFramework\Validation\ValidationRule;

class PhoneRule extends ValidationRule 
{
    protected string $message = "Поле :fieldname: должно содержать валидный номер телефона";
    
    public static function key(): ?string 
    {
        return 'phone';
    }
    
    public function passes(): bool 
    {
        return preg_match('/^\+?[1-9]\d{10,14}$/', $this->value);
    }
}

Использование в валидации:

validate($data, [
    'phone' => 'required|phone'
]);

🎨 CLI команды

# Генерация файлов
php bin/console make:controller UserController
php bin/console make:model User
php bin/console make:middleware RoleMiddleware
php bin/console make:rule CustomRule

# Управление приложением
php bin/console cache:clear       # Очистить кеш
php bin/console app:setup         # Создать структуру директорий

# Помощь
php bin/console help

🗄️ Настройка базы данных

Создание таблиц

Пример таблицы users:

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    role ENUM('user', 'admin') DEFAULT 'user',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

Пример таблицы posts:

CREATE TABLE posts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    slug VARCHAR(255) UNIQUE NOT NULL,
    content TEXT NOT NULL,
    status ENUM('draft', 'published') DEFAULT 'draft',
    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
);

Настройка белого списка таблиц

Отредактируйте config/db.php, чтобы определить разрешенные таблицы:

const TABLES_WHITELIST = [
    'users',
    'posts',
    'comments',
    'categories'
];

🔐 Пример аутентификации

Контроллер входа

public function login(): mixed
{
    if (request()->isPost()) {
        $data = request()->post();
        
        if (!validate($data, [
            'email' => 'required|email',
            'password' => 'required'
        ])) {
            return $this->render('auth/login', [
                'errors' => validator()->errors()
            ]);
        }
        
        $user = db()->table('users')
            ->where('email', $data['email'])
            ->first();
        
        if ($user && password_verify($data['password'], $user['password'])) {
            session()->set('user', $user);
            return response()->redirect('/dashboard')->send();
        }
        
        return $this->render('auth/login', [
            'error' => 'Неверные учетные данные'
        ]);
    }
    
    return $this->render('auth/login');
}

public function logout(): mixed
{
    session()->forget('user');
    return response()->redirect('/')->send();
}

👤 Автор

Владислав Агарков

About

Шаблон для создания новых приложений на кастомном PHP фреймворке

Resources

License

Stars

Watchers

Forks

Packages

No packages published