{"id":15027369,"url":"https://github.com/dahas/f7k","last_synced_at":"2026-02-07T18:34:50.056Z","repository":{"id":152671012,"uuid":"619803924","full_name":"dahas/f7k","owner":"dahas","description":"Yet another PHP framework","archived":false,"fork":false,"pushed_at":"2025-09-23T17:53:28.000Z","size":1493,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-23T19:28:52.318Z","etag":null,"topics":["framework","framework-php","latte","opis","orm","php","php81","template-engine"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dahas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-27T13:22:40.000Z","updated_at":"2025-09-23T17:53:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"b85e86a2-d530-444f-b2a1-71e75095032b","html_url":"https://github.com/dahas/f7k","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/dahas/f7k","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahas%2Ff7k","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahas%2Ff7k/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahas%2Ff7k/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahas%2Ff7k/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dahas","download_url":"https://codeload.github.com/dahas/f7k/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahas%2Ff7k/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29203784,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T17:44:10.191Z","status":"ssl_error","status_checked_at":"2026-02-07T17:44:07.936Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["framework","framework-php","latte","opis","orm","php","php81","template-engine"],"created_at":"2024-09-24T20:06:19.350Z","updated_at":"2026-02-07T18:34:50.050Z","avatar_url":"https://github.com/dahas.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# f7k - yet another framework\n\n\u003cimg src=\"https://img.shields.io/badge/PHP-8.1.2-orange\" /\u003e \u003cimg src=\"https://img.shields.io/badge/Latte-3.x-green\" /\u003e \u003cimg src=\"https://img.shields.io/badge/Opis ORM-1.x-yellow\" /\u003e \u003cimg src=\"https://img.shields.io/badge/PHPUnit-10.x-blue\" /\u003e\n\n- f7k is the numeronym of the word 'framework'.\n- f7k follows the PHP Standard Recommendations (PSR).\n- f7k requires good knowledge of the php programming language.\n- f7k is the most difficult framework on the planet.\n- f7k is so difficult, that only the nerdiest nerds can handle it. \n\n## Minimum Requirements\n\n- PHP 8.1.2\n- Composer\n- A Google Account\n\n## Installation\n````\n$ composer install\n````\n\n## Set Permissions\n````\n$ sudo adduser $USER www-data\n$ sudo chown -R $USER:www-data /var/www/\u003cyour_folder_name\u003e \n$ sudo chmod -R 775 /var/www/\u003cyour_folder_name\u003e\n````\n\n# Setting things up\n\n## Environment variables\n\nRename `.env.example` to `.env`. All sensitive informations are stored in this file. Double check that it is added to `.gitignore` so it won't accidentially appear in your public repository.\n\nOpen the `.env` file and adjust some settings:\n\n- Leave the LOCAL_HOST setting as it is.\n- Set your PUBLIC_DOMAIN if you have one already registered.\n\n# Run locally\n\nLaunch the PHP build-in web server:\n````\n$ php -S localhost:2400 -t public\n````\n\n# How to \n\n## Extend f7k with Controllers\n\nWith a Controller you can extend f7k with new Pages and new Functionality.\n\nCreate a file `MyController.php` in the `controllers` directory:\n\n````php\n// controllers/MyController.php\n\n\u003c?php declare(strict_types=1);\n\nnamespace f7k\\Controller;\n\nuse f7k\\Sources\\attributes\\Route;\nuse f7k\\Sources\\ControllerBase;\n\nclass MyController extends ControllerBase {\n\n    #[Route(path: '/SayMyName/{name}', method: 'get')]\n    public function main(): void\n    {\n        $this-\u003eresponse-\u003ewrite(\"Hello \" . $this-\u003edata['name']);\n    }\n    \n    //...\n}\n````\nCheck it out in the web browser (provide your name):  \nhttp://localhost:2400/SayMyName/\u003cYourName\\\u003e\n\n### Render HTML\n\nNow, if you want to render a beautiful HTML template, you need a Template Engine. \"Latte\" is available as a Service. \"Latte\" is part of the sweet and way too easy \"Nette\" Framework (Good for the rest of the world, but not for the nerdy nerds).\n\nLearn more about Latte here: https://latte.nette.org/en/guide\n\nHere is how you use the Template Service:\n\nCreate an HTML file named `My.partial.html` with the following content in the `templates` folder:  \n\n````html\n{layout 'App.layout.html'}\n\n{block content}\n\u003cdiv style=\"background-color: rgb(196, 250, 255); padding: 20px 0; font-family: 'Courier New', Courier, monospace; margin: 0px auto; text-align: center\"\u003e\n    \u003ch1\u003e{$header}\u003c/h1\u003e\n    \u003cp\u003e{$message}\u003c/p\u003e\n\u003c/div\u003e\n{/block}\n````\nInject the Template Engine as shown below:  \n\n````php\n// controllers/MyController.php\n\n\u003c?php declare(strict_types=1);\n\nnamespace f7k\\Controller;\n\nuse f7k\\Service\\TemplateService;\nuse f7k\\Sources\\attributes\\{Inject, Route};\nuse f7k\\Sources\\ControllerBase;\n\nclass MyController extends ControllerBase {\n\n    #[Inject(TemplateService::class)]\n    protected $template;\n\n    #[Route(path: '/SayMyName/{name}', method: 'get')]\n    public function main(): void\n    {\n        $this-\u003etemplate-\u003eassign([\n            'title' =\u003e 'My Controller',\n            'header' =\u003e 'f7k is cool!',\n            'message' =\u003e 'But ' . $this-\u003edata['name'] . ' is way cooler :p'\n        ]);\n        $this-\u003etemplate-\u003eparse('My.partial.html');\n        $this-\u003etemplate-\u003erender();\n    }\n    \n    //...\n}\n````\nCheck it out again:  \nhttp://localhost:2400/SayMyName/\u003cYourName\\\u003e\n\n## Extend the Menu\n\nFinally, you might want your new page to appear in the navigation bar. Therefore open `menu.json` and insert the following lines:\n\n````\n// ...\n{\n    \"path\": \"/SayMyName/\u003cYourName\\\u003e\",\n    \"controller\": \"MyController\",\n    \"title\": \"Say My Name\",\n    \"enabled\": true\n},\n// ...\n````\nTo see the Menu you have to do one last little change in your Controller: \n````php\nclass MyController extends AppController {\n    \n    //...\n}\n````\nThe `AppController` hosts all the features and services that you need throughout the whole app (like Navigation Bar, Footer, etc.).\n\n## Extend f7k with Services\nA Service is an Object that provides additional features and/or data. Most of the time you will retrieve data from a database table within a Service.  \n\nTo create a Service you simply create a Class in the `services` directory and inject it via an Attribute in the Controller where you need the Service. Name yours `MyService.php`.\n\n````php\n// services/MyService.php\n\n\u003c?php declare(strict_types=1);\n\nnamespace f7k\\Service;\n\nuse f7k\\Sources\\{Request, Response, Session};\n\nclass MyService {\n\n    /**\n     * The constructor is optional. Use it, when you require access \n     * to the Request, Response or Session instances.\n     */\n    public function __construct(\n        protected Request $request, \n        protected Response $response, \n        protected Session $session\n    ) {}\n    //...\n\n    public function myMethod(string $name): string\n    {\n        return \"Hey $name! How can I serve you?\";\n    }\n}\n````\nNow inject the Service in your Controller `MyController.php`:\n````php\n// controllers/AnyController.php\n\nuse f7k\\Service\\{TemplateService, MyService};\n\nclass MyController extends AppController {\n\n    #[Inject(MyService::class)]\n    protected $myService;\n\n    // ...\n}\n````\nTo use the Service assign `$this-\u003emyService-\u003emyMethod(\u003cname\u003e)` to the 'message' marker of the template:\n````php\n#[Route(path: '/SayMyName/{name}', method: 'get')]\npublic function main(): void\n{\n    $this-\u003etemplate-\u003eassign([\n        'title' =\u003e 'Your Controller',\n        'header' =\u003e 'f7k is cool!',\n        'message' =\u003e $this-\u003emyService-\u003emyMethod($this-\u003edata['name'])\n    ]);\n    $this-\u003etemplate-\u003eparse('My.partial.html');\n    $this-\u003etemplate-\u003erender();\n}\n````\nAnd again: http://localhost:2400/SayMyName/\u003cYourName\\\u003e\n\nIt is also possible to use **Services in other Services**. In this case the Constructor is mandatory and the Service must inherit from Class `ServiceBase`.\n\n````php\n// services/MyService.php\n\n\u003c?php declare(strict_types=1);\n\nnamespace f7k\\Service;\n\nuse f7k\\Sources\\{ServiceBase, Request, Response, Session};\n\nclass MyService extends ServiceBase {\n\n    #[Inject(AnotheryService::class)]\n    protected $anotherService;\n\n    public function __construct(\n        protected Request $request, \n        protected Response $response, \n        protected Session $session\n    ) {\n        // Parent Constructor must be triggered!\n        parent::__construct($this-\u003erequest, $this-\u003eresponse, $this-\u003esession);\n    }\n\n    //...\n}\n````\n\n## Enable Google User Authentication\n\nAll kind of authentication and authorization is done externally using the Google OAuth service. Therefore it is neccessary that you have a Google account and have the API enabled. Below is a description of how to enable the Authentication API.\n\n1. In the Google Cloud Console go to API credentials:  \nhttps://console.developers.google.com/apis/credentials?hl=de\n1. Create a new Project\n1. Click on \"Configure Consent Screen\", choose \"External\".\n1. Enter a name and provide your email address.\n1. Skip \"Scopes\" and \"Test Users\" and finish the configuration.\n1. Go back to Credentials, click on \"Create Credentials\" and choose \"OAuth Client ID\".\n1. Select \"Web Application\" as application type.\n1. Copy the LOCAL_HOST and the PUBLIC_DOMAIN from your `.env` file, paste them into authorised redirect URIs and extend both of them with *\"/Authenticate\"*.  \n    E. g.: http://localhost:2400/Authenticate\n1. Save it.\n1. Copy and paste the Client ID and Secret from the final screen into the `.env` file.\n\n## Become the Admin. \nIn the terminal run:\n````\n$ php encrypt.php \u003cyour_gmail_address\u003e\n````\n- Copy the hash and assign it to ACCOUNT_HASH in your `.env` file.\n\n# Available Services \nNext you find some Services that are already available. Feel free to use and/or modify them as you like.\n\n## AuthenticationService\n### *Description*:  \nUse this service to authenticate and authorize users for further actions.\n\n## MarkdownService\n### *Dependencies*:\n* Services: `PurifyService`\n### *Description*:  \nCreates and renders HTML from Markdown.\n\n## MenuService\n### *Dependencies*:\n* Templates: `Menu.partial.html`\n### *Description*:  \nCreates and renders the menu inside the navigation bar according to the specification in `menu.json`.\n\n## PurifyService\n### *Description*:  \nUses HTMLPurifier to remove malicious code.\n\n## TemplateService\n### *Description*:  \nParses HTML templates. \n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdahas%2Ff7k","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdahas%2Ff7k","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdahas%2Ff7k/lists"}