Rumah >pembangunan bahagian belakang >tutorial php >Membina Blog Mudah dengan Penerbangan - Bahagian 1
Hei semua! Saya fikir sudah tiba masanya untuk mempamerkan beberapa ciri baharu yang telah ditambahkan pada Rangka Kerja Penerbangan untuk PHP. Awal tahun ini pencipta asal Flight Mike Cao dengan murah hati menawarkan untuk memindahkan pemilikan mikecao/penerbangan kepada organisasi Flight PHP yang baharu. Memandangkan ia telah dialihkan, kami telah menambahkan ciri seperti perisian tengah, kumpulan laluan, DIC dan ciri lain. Siaran ini akan menjadi lebih lama sedikit, tetapi ini hanya kerana saya telah memasukkan banyak contoh kod supaya anda boleh mempunyai konteks yang betul tentang cara blog anda akan dibina.
Mula-mula, mari kita singkirkan perkara ini. Penerbangan dimaksudkan sebagai rangka kerja mudah dengan beberapa loceng dan wisel. Ia tidak akan bersaing dengan Laravel atau Symfony atau Yii atau Cake atau [isi tempat kosong]. Rangka kerja ini benar-benar dibina ke arah projek bersaiz sederhana hingga sederhana. Ia juga memenuhi keperluan mereka yang tidak suka "sihir" dalam kod mereka yang sukar difahami atau dilatih. Ia lebih menjurus kepada pembangun yang baru mula bercabang ke dalam rangka kerja dan bukannya PHP mentah dengan banyak kenyataan sertakan rawak.
Banyak ciri hebat, pelaksanaan mudah yang bagus, bla bla bla inilah kodnya. Pergi ke bahagian 2 untuk perkara yang menarik!
Jom gunakan Komposer untuk memulakan parti ini.
composer create-project flightphp/skeleton blog/ cd blog/
Perkara pertama yang perlu dilakukan ialah pergi ke fail app/config/config.php di mana kami boleh meletakkan sebarang konfigurasi seperti kunci API, bukti kelayakan pangkalan data dan bukti kelayakan penting lain untuk apl kami. Untuk blog ini, kami akan menyahkomen baris dengan file_path untuk laluan pangkalan data SQLite kami:
return [ 'database' => [ // 'host' => 'localhost', // 'dbname' => 'dbname', // 'user' => 'user', // 'password' => 'password' 'file_path' => __DIR__ . $ds . '..' . $ds . 'database.sqlite' ], ];
Penerbangan kini dilengkapi dengan utiliti baris arahan yang dipanggil landasan. Ini membolehkan anda membuat arahan tersuai untuk pemalam untuk Flight, atau bahkan untuk projek anda sendiri.
Sebagai sebahagian daripada rangka, ia disertakan dengan SampleDatabaseCommand yang akan memberi kami titik permulaan dengan projek blog yang kami buat ini.
Jalankan arahan di bawah dan ia sepatutnya mengisi pangkalan data anda untuk anda!
php runway init:sample-db
Seterusnya kami akan membuka fail app/config/services.php dan nyahkomen baris untuk SQLite.
// see how the $config variable references the config line we uncommented earlier? $dsn = 'sqlite:' . $config['database']['file_path'];
Hanya untuk memastikan kami telah menyediakan semuanya dengan betul, jalankan permulaan komposer dan kemudian pergi ke http://localhost:8000/ dalam penyemak imbas anda. Anda sepatutnya melihat skrin berikut:
Anda juga akan melihat di sudut anda mempunyai bar alat nyahpepijat yang berguna dengan beberapa panel Penerbangan tersuai untuk membantu anda memahami perkara yang berlaku dalam aplikasi anda. Jika anda menuding pada pelbagai item dalam bar alat, anda akan melihat pelbagai tuding yang boleh anda klik untuk kekal melekat pada halaman (lebih lanjut mengenainya kemudian).
Penerbangan datang dengan penyelesaian templat HTML yang sangat asas yang sudah ada dalam rangka kerja. Ini sesuai untuk tapak yang sangat mudah atau hanya untuk mengembalikan sekeping HTML yang ringkas. Adalah disyorkan untuk menggunakan platform templat lain seperti Latte, Twig atau Blade. Dalam tutorial ini, kami akan menggunakan Latte kerana ia hebat dan tidak mempunyai kebergantungan (anda akan perasan dalam Penerbangan kami tidak menyukai kebergantungan yang tidak perlu)!
Teruskan dan pasang Latte
composer require latte/latte
Tambahkan ini pada perkhidmatan anda.php
$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); });
Sekarang kami mempunyai enjin templat, kami boleh mencipta fail HTML asas. Mari buat fail 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>
Flight mempunyai pemalam untuk berinteraksi dengan pangkalan data yang dipanggil Rekod Aktif Penerbangan. Pemalam ini membantu anda tidak menulis sebanyak SQL mentah dalam apl anda (walaupun kadangkala lebih cekap untuk menulis pertanyaan SQL mentah dan bukannya memaksa rekod/ORM/pemeta yang aktif untuk menjalankannya untuk anda). Pada asasnya sambungan rekod aktif membantu anda berinteraksi dengan baris dalam jadual dalam pangkalan data anda: satu baris dalam pangkalan data boleh dipetakan ke objek dalam PHP (dengan autolengkap untuk lajur) menjimatkan masa dan kewarasan. Mari pasangkannya dalam projek kami.
composer require flightphp/active-record
Kini anda boleh menggunakan landasan untuk mencipta kelas rekod aktif anda secara automatik untuk anda dan ia akan mencipta sifat anda sebagai ulasan secara automatik (untuk autolengkap)!
Mula-mula mari kita buat kelas siaran. Kali pertama anda menjalankan ini, ia perlu menyediakan sambungan untuk pangkalan data.
$ 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
Kini kami akan mencipta kelas rekod ulasan:
$ php runway make:record comments
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
And you should see something similar to the following:
$ php runway make:controller Home Controller successfully created at app/controllers/HomeController.php
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' ]); }
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}
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');
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!
Now we're cookin'!
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'); });
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');
With the controller, first let's create an empty controller with runway:
php runway make:controller Post
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'); } }
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();
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");
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}
app/views/posts/show.latte
{extends '../layout.latte'} {block content} <a href="/blog">< 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}
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}
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}
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
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); } }
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'); });
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!
Atas ialah kandungan terperinci Membina Blog Mudah dengan Penerbangan - Bahagian 1. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!