Skip to content

malisahin89/findik-engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FindikEngine — Laravel Tadında Özel PHP Framework

PHP Version License Framework

FindikEngine, Laravel mimarisinden ilham alınarak sıfırdan yazılmış, tam özellikli bir PHP MVC framework'üdür. Routing, DI Container, Auth, Validation, Mail, Event, Pagination, CLI, API Token, Çok Dilli İçerik ve daha fazlasını içerir.

Eğitim ve öğrenme amaçlıdır.


Özellikler

  • Laravel benzeri routing (resource, PUT/DELETE, middleware grupları)
  • Reflection tabanlı IoC Container + DI
  • Laravel-like Request / ResponseBuilder
  • Auth Facade (önbellekli, remember me, API token)
  • Form Validation (20+ kural) + FormRequest
  • Merkezi ExceptionHandler + abort()
  • RBAC — rol & izin yönetimi
  • Rate Limiting (throttle:5,300)
  • Pagination ($items->links())
  • Mail (Mailable pattern, log/smtp driver)
  • Event / Listener sistemi
  • Soft Deletes, Model Factories
  • PHPUnit test altyapısı (43 test)
  • Console CLI (php console make:controller, migrate, vb.)
  • Çok Dilli İçerik (blog, ürün, kategori, sayfa)
  • Admin Panel (RBAC, istatistik grafikleri, log görüntüleyici)
  • Frontend (blog, ürünler, statik sayfalar)
  • CSRF, XSS, SQL Injection, Open Redirect, Session Fixation koruması
  • CSP (nonce tabanlı), güvenlik HTTP başlıkları

Gereksinimler

  • PHP 8.1+
  • MySQL 5.7+ / MariaDB 10.2+
  • Composer
  • Apache (mod_rewrite) veya Nginx
  • PHP extensions: PDO, mbstring, fileinfo, gd

Kurulum

# 1. Bağımlılıkları yükle
composer install

# 2. Environment dosyasını oluştur
cp .env.example .env

# 3. .env içindeki DB bilgilerini doldur

# 4. Migration + Seed çalıştır
#    .env → RUN_MIGRATIONS=true, RUN_SEEDERS=true
#    Sonra herhangi bir sayfayı yükle, ya da:
php console migrate
php console db:seed

# 5. Geliştirme sunucusu
php -S localhost:8000 -t public

.env Yapılandırması

APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost:8000
APP_KEY=your-32-char-secret-key

DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=findikengine
DB_USERNAME=root
DB_PASSWORD=

MAIL_DRIVER=log
MAIL_FROM_ADDRESS=noreply@findikengine.test
MAIL_FROM_NAME=FindikEngine

RUN_MIGRATIONS=false
RUN_SEEDERS=false

Test Kullanıcıları

Email Şifre Rol
admin@findikengine.test 12345678 admin
test@findikengine.test 12345678 member

Proje Yapısı

findik-engine/
├── public/index.php            ← Entry point
├── core/                       ← Framework çekirdeği
│   ├── Application.php         ← Bootstrap orkestratör
│   ├── Auth.php                ← Auth facade (önbellekli)
│   ├── Cache.php               ← HMAC-imzalı dosya cache
│   ├── Container.php           ← IoC Container (Reflection)
│   ├── ExceptionHandler.php    ← Merkezi exception yönetimi
│   ├── FormRequest.php         ← Auto-validating request
│   ├── Language.php            ← Çok dilli sistem singleton
│   ├── Paginator.php           ← Bootstrap 5 sayfalama
│   ├── RateLimiter.php         ← Rate limiter
│   ├── Request.php             ← Laravel-like request
│   ├── ResponseBuilder.php     ← Fluent response builder
│   ├── Route.php               ← Router
│   ├── Validator.php           ← Form doğrulama
│   ├── Console/Kernel.php      ← CLI komutları
│   ├── Events/                 ← Event sistemi
│   ├── Mail/                   ← Mailable / Mailer
│   └── Middleware/             ← SecurityHeaders, VerifyCsrf
├── app/
│   ├── Controllers/
│   │   ├── Auth/               ← Login, Logout, Register
│   │   ├── Admin/              ← Post, Product, Category, Tag, Page, Seo, Language
│   │   ├── Front/              ← Post, Product, Page (public)
│   │   ├── AdminController.php ← İstatistik, izin, log
│   │   └── UserController.php
│   ├── Middleware/             ← Auth, Admin, Permission, Throttle, Locale, ApiAuth
│   ├── Models/                 ← User, Post, Category, Tag, Product, Page, Language + Translations
│   └── Providers/              ← EventServiceProvider
├── config/                     ← app, mail, cache, session, database
├── database/
│   ├── migrations/             ← 14+ migration
│   ├── seeders/                ← Users, Language, Category, Tag, Seo
│   └── factories/              ← UserFactory, PostFactory
├── routes/web.php
├── views/
│   ├── layouts/                ← admin/app.php, front.php, base.php
│   ├── auth/
│   ├── admin/                  ← posts, products, categories, tags, pages, seo, languages
│   ├── front/                  ← posts, products, pages
│   └── errors/                 ← 403, 404, 500
├── tests/                      ← 43 PHPUnit testi
├── stubs/                      ← make:* şablonları
└── console                     ← CLI entry point

Routing

// Temel
Route::get('/about', 'PageController@about')->name('about');
Route::post('/contact', 'ContactController@store')->middleware('throttle:5,60');

// Grup + middleware
Route::prefix('/admin')->middleware('auth')->group(function () {
    Route::get('/dashboard', 'DashboardController@index')->name('dashboard');
    Route::get('/{id}/edit', 'UserController@edit')->name('admin.users.edit');
    Route::put('/{id}', 'UserController@update')->name('admin.users.update');
    Route::delete('/{id}', 'UserController@destroy')->name('admin.users.destroy');
});

// Resource CRUD (7 route tek satır)
Route::resource('users', 'UserController');
Route::apiResource('api/posts', 'Api\\PostController');

// Yardımcı
Route::view('/home', 'welcome', ['title' => 'Ana Sayfa']);
Route::redirect('/old', '/new', 301);

// Method spoofing (HTML form)
echo method_field('DELETE'); // <input type="hidden" name="_method" value="DELETE">

Controller

namespace App\Controllers;

use Core\Request;

class PostController
{
    // DI: Request otomatik inject edilir
    public function store(Request $request)
    {
        $data = $request->only(['title', 'content']);

        if ($request->hasFile('cover')) {
            $path = \Core\FileUpload::upload($request->file('cover'), 'uploads/posts');
        }

        Post::create($data);
        flash('success', 'Yazı oluşturuldu.');
        redirect(route('admin.posts.index'));
    }
}

FormRequest (Auto-Validation)

// app/Requests/StorePostRequest.php
class StorePostRequest extends \Core\FormRequest
{
    public function rules(): array
    {
        return [
            'title'   => 'required|min:3|max:255',
            'content' => 'required|min:10',
            'email'   => 'required|email|unique:users,email',
        ];
    }
    public function messages(): array
    {
        return ['title.required' => 'Başlık zorunludur.'];
    }
}

// Controller — validation otomatik, başarısızsa back() + flash errors
public function store(StorePostRequest $request)
{
    $data = $request->validated();
    Post::create($data);
}

Auth

Auth::check()          // bool
Auth::user()           // ?User (request başına tek DB sorgusu)
Auth::id()             // ?int
Auth::attempt(['email' => $e, 'password' => $p, 'remember' => true])
Auth::login($user)
Auth::logout()

// API Token
[$plain, $token] = Auth::createToken($user, 'mobile', ['posts.read']);
Auth::loginWithToken($plainToken);
Auth::revokeTokens($user);

Çok Dilli Sistem

// Aktif dil
Language::current()     // 'tr', 'en', 'ru', 'fr'
Language::set('en')     // Dil ayarla
Language::defaultSlug() // Varsayılan dil slug'ı
Language::all()         // Tüm aktif diller

// URL üretimi
current_lang()                   // 'tr'
lang_url('/posts/slug', 'en')    // '/en/posts/slug'
lang_switch_url('en')            // Mevcut sayfanın İngilizce URL'i
front_route('posts.show', ['slug' => 'hello-world'])

Route Pattern:

// Varsayılan dil (prefix yok)
Route::get('/posts/{slug}', 'Front\\PostController@show');

// Diğer diller
Route::prefix('/{lang}')->middleware('locale')->group(function () {
    Route::get('/posts/{slug}', 'Front\\PostController@show');
});

Event Sistemi

// Dispatch
event(new UserRegistered($user));

// Listener tanımı (app/Providers/EventServiceProvider.php)
protected array $listen = [
    UserRegistered::class => [SendWelcomeEmail::class],
];

// Closure listener
Dispatcher::listen(UserRegistered::class, fn($e) => logger($e->user->id));
Dispatcher::once(OrderPlaced::class, fn($e) => notifyAdmin($e));

Mail

// app/Mail/WelcomeMail.php
class WelcomeMail extends Mailable {
    public function build(): static {
        return $this->subject('Hoş Geldiniz!')
                    ->view('emails/welcome', ['user' => $this->user]);
    }
}

// Gönderim
Mail::to($user->email)->send(new WelcomeMail($user));
Mail::to('a@b.com')->cc('c@b.com')->send(new OrderMail($order));

Console CLI

# Kod üretme
php console make:controller Admin/Report
php console make:model Comment
php console make:migration create_comments_table
php console make:middleware Role
php console make:request StorePost
php console make:mail Welcome
php console make:event OrderPlaced
php console make:listener SendInvoice
php console make:factory Comment
php console make:test UserAuth

# Veritabanı
php console migrate
php console migrate:rollback
php console migrate:fresh
php console db:seed

# Yardım
php console route:list
php console cache:clear
php console test
php console help

Güvenlik

Koruma Yöntem
CSRF Session token, VerifyCsrfToken middleware
XSS Plates e(), htmlspecialchars()
SQL Injection Eloquent ORM, prepared statements
Open Redirect Host whitelist (Redirect::to())
Session Fixation session_regenerate_id(true) login/logout'ta
Brute-force IP + email bazlı rate limiting
MIME Spoofing finfo ile gerçek MIME kontrolü
Path Traversal basename() + regex (log viewer)
CSP Nonce tabanlı, prod'da strict
Şifre bcrypt (PASSWORD_DEFAULT)

Geliştirici

Muhammet Ali ŞAHİN

Detaylı referans: FRAMEWORK.md | Proje geçmişi: PROJE_OZETI.md

About

A lightweight Laravel-inspired PHP micro framework with Eloquent ORM, middleware support, CSRF protection, and a Blade-like templating system powered by Plates.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors