Skip to content

dahas/f7k

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

f7k - yet another framework

  • f7k is the numeronym of the word 'framework'.
  • f7k follows the PHP Standard Recommendations (PSR).
  • f7k requires good knowledge of the php programming language.
  • f7k is the most difficult framework on the planet.
  • f7k is so difficult, that only the nerdiest nerds can handle it.

Minimum Requirements

  • PHP 8.1.2
  • Composer
  • A Google Account

Installation

$ cd /var/www
$ sudo git clone https://github.com/dahas/f7k.git <your_folder_name>
$ cd <your_folder_name>
$ composer install

Set Permissions

$ sudo adduser $USER www-data
$ sudo chown -R $USER:www-data /var/www/<your_folder_name> 
$ sudo chmod -R 775 /var/www/<your_folder_name>

Setting things up

Environment variables

Rename .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.

Open the .env file and adjust some settings:

  • Leave the LOCAL_HOST setting as it is.
  • Set your PUBLIC_DOMAIN if you have one already registered.

Run locally

Launch the PHP build-in web server:

$ php -S localhost:2400 -t public

How to

Extend f7k with Controllers

With a Controller you can extend f7k with new Pages and new Functionality.

Create a file MyController.php in the controllers directory:

// controllers/MyController.php

<?php declare(strict_types=1);

namespace f7k\Controller;

use f7k\Sources\attributes\Route;
use f7k\Sources\ControllerBase;

class MyController extends ControllerBase {

    #[Route(path: '/SayMyName/{name}', method: 'get')]
    public function main(): void
    {
        $this->response->write("Hello " . $this->data['name']);
    }
    
    //...
}

Check it out in the web browser (provide your name):
http://localhost:2400/SayMyName/<YourName>

Render HTML

Now, 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).

Learn more about Latte here: https://latte.nette.org/en/guide

Here is how you use the Template Service:

Create an HTML file named My.partial.html with the following content in the templates folder:

{layout 'App.layout.html'}

{block content}
<div style="background-color: rgb(196, 250, 255); padding: 20px 0; font-family: 'Courier New', Courier, monospace; margin: 0px auto; text-align: center">
    <h1>{$header}</h1>
    <p>{$message}</p>
</div>
{/block}

Inject the Template Engine as shown below:

// controllers/MyController.php

<?php declare(strict_types=1);

namespace f7k\Controller;

use f7k\Service\TemplateService;
use f7k\Sources\attributes\{Inject, Route};
use f7k\Sources\ControllerBase;

class MyController extends ControllerBase {

    #[Inject(TemplateService::class)]
    protected $template;

    #[Route(path: '/SayMyName/{name}', method: 'get')]
    public function main(): void
    {
        $this->template->assign([
            'title' => 'My Controller',
            'header' => 'f7k is cool!',
            'message' => 'But ' . $this->data['name'] . ' is way cooler :p'
        ]);
        $this->template->parse('My.partial.html');
        $this->template->render();
    }
    
    //...
}

Check it out again:
http://localhost:2400/SayMyName/<YourName>

Extend the Menu

Finally, you might want your new page to appear in the navigation bar. Therefore open menu.json and insert the following lines:

// ...
{
    "path": "/SayMyName/<YourName\>",
    "controller": "MyController",
    "title": "Say My Name",
    "enabled": true
},
// ...

To see the Menu you have to do one last little change in your Controller:

class MyController extends AppController {
    
    //...
}

The AppController hosts all the features and services that you need throughout the whole app (like Navigation Bar, Footer, etc.).

Extend f7k with Services

A 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.

To 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.

// services/MyService.php

<?php declare(strict_types=1);

namespace f7k\Service;

use f7k\Sources\{Request, Response, Session};

class MyService {

    /**
     * The constructor is optional. Use it, when you require access 
     * to the Request, Response or Session instances.
     */
    public function __construct(
        protected Request $request, 
        protected Response $response, 
        protected Session $session
    ) {}
    //...

    public function myMethod(string $name): string
    {
        return "Hey $name! How can I serve you?";
    }
}

Now inject the Service in your Controller MyController.php:

// controllers/AnyController.php

use f7k\Service\{TemplateService, MyService};

class MyController extends AppController {

    #[Inject(MyService::class)]
    protected $myService;

    // ...
}

To use the Service assign $this->myService->myMethod(<name>) to the 'message' marker of the template:

#[Route(path: '/SayMyName/{name}', method: 'get')]
public function main(): void
{
    $this->template->assign([
        'title' => 'Your Controller',
        'header' => 'f7k is cool!',
        'message' => $this->myService->myMethod($this->data['name'])
    ]);
    $this->template->parse('My.partial.html');
    $this->template->render();
}

And again: http://localhost:2400/SayMyName/<YourName>

It is also possible to use Services in other Services. In this case the Constructor is mandatory and the Service must inherit from Class ServiceBase.

// services/MyService.php

<?php declare(strict_types=1);

namespace f7k\Service;

use f7k\Sources\{ServiceBase, Request, Response, Session};

class MyService extends ServiceBase {

    #[Inject(AnotheryService::class)]
    protected $anotherService;

    public function __construct(
        protected Request $request, 
        protected Response $response, 
        protected Session $session
    ) {
        // Parent Constructor must be triggered!
        parent::__construct($this->request, $this->response, $this->session);
    }

    //...
}

Enable Google User Authentication

All 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.

  1. In the Google Cloud Console go to API credentials:
    https://console.developers.google.com/apis/credentials?hl=de
  2. Create a new Project
  3. Click on "Configure Consent Screen", choose "External".
  4. Enter a name and provide your email address.
  5. Skip "Scopes" and "Test Users" and finish the configuration.
  6. Go back to Credentials, click on "Create Credentials" and choose "OAuth Client ID".
  7. Select "Web Application" as application type.
  8. 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".
    E. g.: http://localhost:2400/Authenticate
  9. Save it.
  10. Copy and paste the Client ID and Secret from the final screen into the .env file.

Become the Admin.

In the terminal run:

$ php encrypt.php <your_gmail_address>
  • Copy the hash and assign it to ACCOUNT_HASH.

Available Services

Next you find some Services that are already available. Feel free to use and/or modify them as you like.

AuthenticationService

Description:

Use this service to authenticate and authorize users for further actions.

MarkdownService

Dependencies:

  • Services: PurifyService

Description:

Creates and renders HTML from Markdown.

MenuService

Dependencies:

  • Templates: Menu.partial.html

Description:

Creates and renders the menu inside the navigation bar according to the specification in menu.json.

PurifyService

Description:

Uses HTMLPurifier to remove malicious code.

TemplateService

Description:

Parses HTML templates.