Heim > Backend-Entwicklung > PHP-Tutorial > Erstellen eines einfachen Blogs mit Flight – Teil 1

Erstellen eines einfachen Blogs mit Flight – Teil 1

PHPz
Freigeben: 2024-07-18 01:21:41
Original
1231 Leute haben es durchsucht

Hallo zusammen! Ich dachte, es wäre an der Zeit, einige der neuen Funktionen vorzustellen, die dem Flight Framework für PHP hinzugefügt wurden. Anfang des Jahres bot Mike Cao, der ursprüngliche Erfinder von Flight, freundlicherweise an, die Eigentümerschaft von mikecao/flight an eine neue Flight-PHP-Organisation zu übertragen. Seit der Verschiebung haben wir Funktionen wie Middleware, Routengruppierung, DIC und andere Funktionen hinzugefügt. Dieser Beitrag wird etwas länger sein, aber das liegt nur daran, dass ich viele Codebeispiele eingefügt habe, damit Sie den richtigen Kontext für die Erstellung Ihres Blogs haben.

Lasst uns das zunächst einmal aus dem Weg räumen. Flight soll ein einfaches Framework mit ein paar Schnickschnack sein. Es konkurriert nicht mit Laravel, Symfony, Yii, Cake oder [Füllen Sie die Lücke aus]. Dieses Framework ist wirklich für einfache bis mittelgroße Projekte konzipiert. Es richtet sich auch an diejenigen, die keine „Magie“ in ihrem Code mögen, die schwer zu verstehen oder zu erlernen ist. Es richtet sich eher an Entwickler, die gerade erst anfangen, in Frameworks zu verzweigen, statt in reines PHP mit vielen zufälligen Include-Anweisungen.

tl;dr

Viele coole Funktionen, schöne einfache Implementierung, bla bla bla, hier ist der Code. Gehen Sie zu Teil 2 für die coolen Sachen!

Installation

Lassen Sie uns Composer verwenden, um diese Party zu starten.

composer create-project flightphp/skeleton blog/
cd blog/
Nach dem Login kopieren

Konfigurieren Sie Ihr neues Projekt

Als Erstes gehen wir zur Datei app/config/config.php, wo wir beliebige Konfigurationen wie API-Schlüssel, Datenbankanmeldeinformationen und andere wichtige Anmeldeinformationen für unsere App hinterlegen können. Für diesen Blog werden wir die Zeile mit file_path für unseren SQLite-Datenbankpfad auskommentieren:

return [
    'database' => [
        // 'host' => 'localhost',
        // 'dbname' => 'dbname',
        // 'user' => 'user',
        // 'password' => 'password'
        'file_path' => __DIR__ . $ds . '..' . $ds . 'database.sqlite'
    ],
];
Nach dem Login kopieren

Erstellen Sie die Blog-Datenbank

Flight wird jetzt mit einem Befehlszeilenprogramm namens runway geliefert. Dadurch können Sie benutzerdefinierte Befehle für ein Plugin für Flight oder sogar für Ihr eigenes Projekt erstellen.

Als Teil des Grundgerüsts wird ein SampleDatabaseCommand mitgeliefert, der uns einen Ausgangspunkt für dieses Blog-Projekt gibt, das wir erstellen.

Führen Sie den folgenden Befehl aus und Ihre Datenbank sollte automatisch gefüllt werden!

php runway init:sample-db
Nach dem Login kopieren

Als nächstes öffnen wir die Datei app/config/services.php und kommentieren die Zeile für SQLite aus.

// see how the $config variable references the config line we uncommented earlier?
$dsn = 'sqlite:' . $config['database']['file_path'];
Nach dem Login kopieren

Um sicherzustellen, dass alles richtig eingerichtet ist, führen Sie Composer Start aus und gehen Sie dann in Ihrem Browser zu http://localhost:8000/. Sie sollten den folgenden Bildschirm sehen:

Default Home Page

Sie werden außerdem feststellen, dass Sie in der Ecke eine praktische Debug-Symbolleiste mit einigen benutzerdefinierten Flight-Panels haben, die Ihnen helfen, zu verstehen, was in Ihrer Anwendung vor sich geht. Wenn Sie mit der Maus über die verschiedenen Elemente in der Symbolleiste fahren, werden verschiedene Hover angezeigt, auf die Sie klicken können, um sie auf der Seite festzuhalten (dazu später mehr).

Flight Tracy Extensions

Erstellen der HTML-Vorlagen

Flight verfügt bereits über eine sehr einfache HTML-Vorlagenlösung im Framework. Dies ist für sehr einfache Websites oder einfach zum Zurückgeben eines einfachen HTML-Stücks völlig ausreichend. Es wird empfohlen, eine andere Vorlagenplattform wie Latte, Twig oder Blade zu verwenden. In diesem Tutorial verwenden wir Latte, weil es fantastisch ist und keine Abhängigkeiten hat (Sie werden feststellen, dass wir in Flight keine unnötigen Abhängigkeiten mögen)!

Machen Sie weiter und installieren Sie Latte

composer require latte/latte
Nach dem Login kopieren

Fügen Sie dies zu Ihrer Services.php hinzu

$Latte = new \Latte\Engine;
$Latte->setTempDirectory(__DIR__ . '/../cache/');

// This is fun feature of Flight. You can remap some built in functions with the framework
// to your liking. In this case, we're remapping the Flight::render() method.
$app->map('render', function(string $templatePath, array $data = [], ?string $block = null) use ($app, $Latte) {
    $templatePath = __DIR__ . '/../views/'. $templatePath;
    $Latte->render($templatePath, $data, $block);
});
Nach dem Login kopieren

Da wir nun über eine Template-Engine verfügen, können wir eine Basis-HTML-Datei erstellen. Erstellen wir eine Datei „layout.latte“:

<!doctype html>
<html lang="en">
    <head>
        <!-- Picnic.css is a CSS framework that works out of the box with little configuration -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/picnic">
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>{$page_title ? $page_title.' - '}Blog Built with Flight!</title>
    </head>
    <body style="padding: 15px;">
        {block content}{/block}
    </body>
</html>
Nach dem Login kopieren

Datenbankklasse für aktive Datensätze

Flight verfügt über ein Plugin für die Interaktion mit einer Datenbank namens Flight Active Record. Dieses Plugin hilft Ihnen, nicht so viel Roh-SQL in Ihre Apps zu schreiben (obwohl es manchmal effizienter ist, eine Roh-SQL-Abfrage zu schreiben, anstatt einen aktiven Datensatz/ORM/Mapper zu zwingen, sie für Sie auszuführen). Grundsätzlich hilft Ihnen die Active-Record-Erweiterung bei der Interaktion mit Zeilen in Tabellen in Ihrer Datenbank: Eine Zeile in einer Datenbank kann einem Objekt in PHP zugeordnet werden (mit automatischer Vervollständigung für die Spalten), was Zeit und Verstand spart. Lassen Sie es uns in unserem Projekt installieren.

composer require flightphp/active-record
Nach dem Login kopieren

Jetzt können Sie runway verwenden, um Ihre aktiven Datensatzklassen automatisch für Sie zu erstellen, und Ihre Eigenschaften werden automatisch als Kommentare erstellt (zur automatischen Vervollständigung)!

Erstellen wir zunächst die Beitragsklasse. Wenn Sie dies zum ersten Mal ausführen, muss die Verbindung für die Datenbank eingerichtet werden.

$ php runway make:record posts
Database configuration not found. Please provide the following details:
Driver (mysql/pgsql/sqlite): sqlite
Database file path [database.sqlite]: app/database.sqlite
Username (for no username, press enter) []: 
Password (for no password, press enter) []: 
Writing database configuration to .runway-config.json
Creating directory app/records
Active Record successfully created at app/records/PostRecord.php
Nach dem Login kopieren

Jetzt erstellen wir die Kommentar-Datensatzklasse:

$ php runway make:record comments
Nach dem Login kopieren

It's Time for your First Page!

Flight uses the MVC pattern. In order to create a new page you need to define a route in your routes.php file, create a new method in a controller, and then create the HTML file that the browser will serve. You can use runway to help you get started with a new controller class:

php runway make:controller Home
Nach dem Login kopieren

And you should see something similar to the following:

$ php runway make:controller Home
Controller successfully created at app/controllers/HomeController.php
Nach dem Login kopieren

If you go to app/controllers/HomeController.php go ahead and add this new method to your HomeController:

/**
 * Index
 * 
 * @return void
 */
public function index(): void
{
    $this->app->render('home.latte', [ 'page_title' => 'Home' ]);
}
Nach dem Login kopieren

And create a new file in app/views/home.latte and put in this code:

{extends 'layout.latte'}

{block content}
<h1>My Home Page</h1>
<p><a href="/blog">View My Blog!</a></p>
{/block}
Nach dem Login kopieren

Finally let's change up the routes to the routes.php file. Go ahead and remove any code in the routes file that begins with $router-> and add a new route for your home router:

$router->get('/', \app\controllers\HomeController::class . '->index');
Nach dem Login kopieren

Make sure you run composer start so that your development server is up. If you go to http://localhost:8000/ in your browser, you should see something like this!

Flight Demo Home Page

Now we're cookin'!

Adding Routes for the Blog

Let's go ahead and add all the methods in your controller, routes, and html files. Let's start with adding the routes in your routes.php file:

// Blog
$router->group('/blog', function(Router $router) {

    // Posts
    $router->get('', \app\controllers\PostController::class . '->index');
    $router->get('/create', \app\controllers\PostController::class . '->create');
    $router->post('', \app\controllers\PostController::class . '->store');
    $router->get('/@id', \app\controllers\PostController::class . '->show');
    $router->get('/@id/edit', \app\controllers\PostController::class . '->edit');
    $router->post('/@id/edit', \app\controllers\PostController::class . '->update');
    $router->get('/@id/delete', \app\controllers\PostController::class . '->destroy');
});
Nach dem Login kopieren

So you'll notice we use a group() method here to group all the routes together that start with /blog. We could actually rewrite the routes like the following with the group() method and the same thing would happen:

// Posts
$router->get('/blog', \app\controllers\PostController::class . '->index');
$router->get('/blog/create', \app\controllers\PostController::class . '->create');
Nach dem Login kopieren

With the controller, first let's create an empty controller with runway:

php runway make:controller Post
Nach dem Login kopieren

You can copy the code below for your PostController.php:

<?php

declare(strict_types=1);

namespace app\controllers;

use app\records\CommentRecord;
use app\records\PostRecord;
use flight\Engine;

class PostController
{
    /** @var Engine */
    protected Engine $app;

    /**
     * Constructor
     */
    public function __construct(Engine $app)
    {
        $this->app = $app;
    }

    /**
     * Index
     *
     * @return void
     */
    public function index(): void
    {
        $PostRecord = new PostRecord($this->app->db());
        $posts = $PostRecord->order('id DESC')->findAll();
        $CommentRecord = new CommentRecord($this->app->db());
        foreach($posts as &$post) {
            $post->comments = $CommentRecord->eq('post_id', $post->id)->findAll();
        }
        $this->app->render('posts/index.latte', [ 'page_title' => 'Blog', 'posts' => $posts]);
    }

    /**
     * Create
     *
     * @return void
     */
    public function create(): void
    {
        $this->app->render('posts/create.latte', [ 'page_title' => 'Create Post']);
    }

    /**
     * Store
     *
     * @return void
     */
    public function store(): void
    {
        $postData = $this->app->request()->data;
        $PostRecord = new PostRecord($this->app->db());
        $PostRecord->title = $postData->title;
        $PostRecord->content = $postData->content;
        $PostRecord->username = $postData->username;
        $PostRecord->created_at = gmdate('Y-m-d H:i:s');
        $PostRecord->updated_at = null;
        $PostRecord->save();
        $this->app->redirect('/blog');
    }

    /**
     * Show
     *
     * @param int $id The ID of the post
     * @return void
     */
    public function show(int $id): void
    {
        $PostRecord = new PostRecord($this->app->db());
        $post = $PostRecord->find($id);
        $CommentRecord = new CommentRecord($this->app->db());
        $post->comments = $CommentRecord->eq('post_id', $post->id)->findAll();
        $this->app->render('posts/show.latte', [ 'page_title' => $post->title, 'post' => $post]);
    }

    /**
     * Edit
     *
     * @param int $id The ID of the post
     * @return void
     */
    public function edit(int $id): void
    {
        $PostRecord = new PostRecord($this->app->db());
        $post = $PostRecord->find($id);
        $this->app->render('posts/edit.latte', [ 'page_title' => 'Update Post', 'post' => $post]);
    }

    /**
     * Update
     *
     * @param int $id The ID of the post
     * @return void
     */
    public function update(int $id): void
    {
        $postData = $this->app->request()->data;
        $PostRecord = new PostRecord($this->app->db());
        $PostRecord->find($id);
        $PostRecord->title = $postData->title;
        $PostRecord->content = $postData->content;
        $PostRecord->username = $postData->username;
        $PostRecord->updated_at = gmdate('Y-m-d H:i:s');
        $PostRecord->save();
        $this->app->redirect('/blog');
    }

    /**
     * Destroy
     *
     * @param int $id The ID of the post
     * @return void
     */
    public function destroy(int $id): void
    {
        $PostRecord = new PostRecord($this->app->db());
        $post = $PostRecord->find($id);
        $post->delete();
        $this->app->redirect('/blog');
    }
}
Nach dem Login kopieren

Let's kill some time and talk about a few things that are going on in the controller.

First off we are now using our new active record classes:

$PostRecord = new PostRecord($this->app->db());
$posts = $PostRecord->order('id DESC')->findAll();
Nach dem Login kopieren

We are injecting the database we setup in the services.php file above with $this->app->db();. Technically we could also just use Flight::db() as this points to the global $app variable.

Active Record classes are really helpful to simplify interactions with a database. We could rewrite the above in the following code:

$posts = $this->app->db()->fetchAll("SELECT * FROM posts ORDER BY id DESC");
Nach dem Login kopieren

This might not be the best example of how helpful an active record could be. But in part 2 I'll show you some hidden gems inside these classes that make it so much better than writing raw SQL.

Now let's talk HTML files. Here are the files we'll need for the post routes:

app/views/posts/index.latte

{extends '../layout.latte'}

{block content}

<h1>My Amazing Blog</h1>
<p>Welcome to my blog!</p>
<p><a class="button" href="/blog/create">Create a new post</a></p>
{foreach $posts as $post}
    {first}
    <h2>Recent Posts</h2>
    {/first}
    <hr>
    <h3><a href="/blog/{$post->id}">{$post->title}</a></h3>
    <p><small>By: {$post->username} on {$post->created_at|date:'d.m.Y G:i a'}</small></p>
    <p>Comments: {count($post->comments)}
    <p>{$post->content|truncate:100}</p>
    <hr>
    <a class="pseudo button" href="/blog/{$post->id}/edit">Update</a> - <a class="pseudo button" href="/blog/{$post->id}/delete">Delete</a>
{/foreach}

{/block}
Nach dem Login kopieren

app/views/posts/show.latte

{extends '../layout.latte'}

{block content}
<a href="/blog">&lt; Back to blog</a>
<h1>{$post->title}</h1>
<p>Created by: {$post->username} on {$post->created_at|date:'d.m.Y G:i a'}.</p>
<div>
    {$post->content|breakLines}
</div>
<p n:if="$post->update_at">Last update: {$post->update_at|date:'d.m.Y G:i a'}.</p>

<h2>Comments</h2>
{foreach $post->comments as $comment}
<div>
    <p>{$comment->username} on {$comment->created_at|date:'d.m.Y G:i a'}.</p>
    <div>
        {$comment->content|breakLines}
    </div>
    <hr>
    <a class="pseudo button" href="/blog/{$post->id}/comment/{$comment->id}/delete">Delete</a>
</div>
{else}
<p>No comments yet.</p>
{/foreach}

<h2>Add comment</h2>
<form action="/blog/{$post->id}/comment" method="post">
    <div>
        <label for="username">Username:</label>
        <input name="username" id="username" placeholder="Username" required />
    </div>
    <div>
        <label for="content">Comment:</label>
        <textarea name="content" id="content" placeholder="Comment" required></textarea>
    </div>
    <div>
        <button type="submit">Add Comment</button>
    </div>
</form>
{/block}
Nach dem Login kopieren

app/views/posts/create.latte

{extends '../layout.latte'}

{block content}
<h1>Create a Post</h1>
<form action="/blog" method="post">
    <label><input type="text" name="title" placeholder="Title" required></label>
    <label><textarea name="content" placeholder="Content" required></textarea></label>
    <label><input type="text" name="username" placeholder="Username" required></label>

    <button type="submit">Create</button>
</form>
{/block}
Nach dem Login kopieren

app/views/posts/edit.latte

{extends '../layout.latte'}

{block content}
<h1>Update a Post</h1>
<form action="/blog/{$post->id}/edit" method="post">
    <label for="title">Title</label>
    <input type="text" name="title" placeholder="Title" value="{$post->title}" required>

    <label for="content">Content</label>
    <label><textarea name="content" placeholder="Content" required>{$post->content}</textarea>

    <label for="username">Username</label>
    <label><input type="text" name="username" placeholder="Username" value="{$post->username}" required>

    <button type="submit">Update</button>
</form>
{/block}
Nach dem Login kopieren

Create a new post

Now that we've got all the pieces in place, you should be able to load up your blog page, create a new post, see a post, and delete a post. You may have noticed we've included a comment form but the form doesn't actually work. We can fix that real quick! Let's create a controller with runway:

php runway make:controller Comment
Nach dem Login kopieren

Now you can make the CommentController.php look like the following:

<?php

declare(strict_types=1);

namespace app\controllers;

use app\records\CommentRecord;
use flight\Engine;

class CommentController
{
    /** @var Engine */
    protected Engine $app;

    /**
     * Constructor
     */
    public function __construct(Engine $app)
    {
        $this->app = $app;
    }

    /**
     * Store
     * 
     * @param int $id The post ID
     * 
     * @return void
     */
    public function store(int $id): void
    {
        $postData = $this->app->request()->data;
        $CommentRecord = new CommentRecord($this->app->db());
        $CommentRecord->post_id = $id;
        $CommentRecord->username = $postData->username;
        $CommentRecord->content = $postData->content;
        $CommentRecord->created_at = gmdate('Y-m-d H:i:s');
        $CommentRecord->updated_at = null;
        $CommentRecord->save();
        $this->app->redirect('/blog/' . $id);
    }

    /**
     * Destroy
     * 
     * @param int $id The post ID
     * @param int $comment_id The comment ID
     * 
     * @return void
     */
    public function destroy(int $id, int $comment_id): void
    {
        $CommentRecord = new CommentRecord($this->app->db());
        $CommentRecord->find($comment_id);
        $CommentRecord->delete();
        $this->app->redirect('/blog/' . $id);
    }

}
Nach dem Login kopieren

Now let's add a couple other routes in the group chunk of code in routes.php

// Blog
$router->group('/blog', function(Router $router) {

    // Posts

    // post routes...

    // Comments
    $router->post('/@id/comment', \app\controllers\CommentController::class . '->store');
    $router->get('/@id/comment/@comment_id/delete', \app\controllers\CommentController::class . '->destroy');
});
Nach dem Login kopieren

Conclusion (sort of)

With these two additions to the code, you have a fully functioning blog built with Flight! This got the job done and you now have a blog, but the code is somewhat clunky and could be improved to have some pretty nifty features like middleware, permissions, and writing less code! Hop over to part 2

Go ahead and leave any questions in comments below or join us in the chatroom!

If you want to see the final product with all the improvements here's the code!

Das obige ist der detaillierte Inhalt vonErstellen eines einfachen Blogs mit Flight – Teil 1. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage