Tutorial Portal Berita - Level 1: Persiapan Proyek
Level 1 dari Tutorial Portal Berita berfokus pada membangun fondasi proyek kita. Bagian ini dirancang untuk diikuti dalam waktu sekitar 7 menit, mencakup langkah-langkah awal yang penting untuk mempersiapkan proyek portal berita kita untuk pengembangan.
Panduan Implementasi
Mari kita mulai mengimplementasikan aplikasi portal berita kita, dimulai dengan fitur-fitur penting di Level 1.
Persiapan Proyek
1. Buat Proyek Laravel Baru
Mari kita inisiasi proyek kita dengan menginstal Laravolt, yang akan membantu kita dalam membangun aplikasi portal berita kita.
composer create-project laravel/laravel news-portal
cd news-portal
Untuk memastikan riwayat code changes kita tersimpan dengan baik, kita akan menggunakan git untuk mengelola riwayat perubahan kode kita. Mari kita inisialisasi repositori git:
git init
Kita akan langsung membuat commit awal untuk menyimpan fresh Laravel project kita:
git add .
git commit -m "Initial commit: Fresh Laravel project"
2. Instal Laravolt
composer require laravolt/laravolt
php artisan laravolt:install
3. Show Off Code Coverage
Setelah menginstal aplikasi Laravolt, kita dapat menjalankan perintah berikut untuk menampilkan cakupan kode (code coverage):
XDEBUG_MODE=coverage php artisan test --coverage
Catatan: Pastikan Anda telah menginstal ekstensi PHP bernama XDebug.
Cakupan kode total dari instalasi baru Laravolt adalah 98,7%. Dengan memastikan cakupan kode yang tinggi, kita dapat merasa percaya diri bahwa kita memulai proyek kita dengan fondasi yang kuat.
4. Atur Lingkungan
Konfigurasikan file .env
kita dengan pengaturan database yang sesuai:
DB_CONNECTION=sqlite
Sekarang, kita perlu menjalankan migrasi untuk membuat tabel yang diperlukan:
php artisan migrate
Mari kita lakukan commit untuk menyimpan perubahan ini:
git add .
git commit -m "Setup environment and database configuration"
Struktur Database
1. Buat Model dan Migrasi
Pertama, mari kita buat model dan juga migrasi yang diperlukan untuk proyek kita:
php artisan make:model Topic -m
php artisan make:model Post -m
php artisan make:model Comment -m
Laravel akan membuat file migrasi untuk setiap model yang kita buat. Mari kita perbarui file migrasi yang dihasilkan untuk mencakup kolom yang diperlukan.
2. Definisikan Skema Topik
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Jalankan migrasi.
*/
// database/migrations/xxxx_xx_xx_create_topics_table.php
public function up()
{
Schema::create('topics', function (Blueprint $table) {
$table->ulid()->primary();
$table->string('name');
$table->string('slug')->unique();
$table->text('description')->nullable();
$table->timestamps();
$table->softDeletes();
});
}
/**
* Balikkan migrasi.
*/
public function down(): void
{
Schema::dropIfExists('topics');
}
};
3. Definisikan Skema Post
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Jalankan migrasi.
*/
// database/migrations/xxxx_xx_xx_create_posts_table.php
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->ulid()->primary();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignUlid('topic_id')->constrained()->onDelete('cascade');
$table->string('title');
$table->string('slug')->unique();
$table->text('summary')->nullable();
$table->longText('content');
$table->string('featured_image')->nullable();
$table->timestamp('published_at')->nullable();
$table->timestamps();
$table->softDeletes();
});
}
/**
* Balikkan migrasi.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
4. Definisikan Skema Komentar
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Jalankan migrasi.
*/
// database/migrations/xxxx_xx_xx_create_comments_table.php
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->ulid()->primary();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignUlid('post_id')->constrained()->onDelete('cascade');
$table->text('content');
$table->boolean('is_approved')->default(false);
$table->timestamps();
$table->softDeletes();
});
}
/**
* Balikkan migrasi.
*/
public function down(): void
{
Schema::dropIfExists('comments');
}
};
Manajemen Peran dan Izin
Karena kita akan menggunakan sistem ACL (Access Control List) bawaan Laravolt, mari kita atur peran dan izin yang diperlukan untuk aplikasi portal berita kita.
1. Buat Enum Izin
Perbarui enum Izin untuk menyertakan semua tindakan yang dapat dilakukan di portal berita kita:
<?php
namespace App\Enums;
use BenSampo\Enum\Enum;
final class Permission extends Enum
{
// Akses dasbor
const DASHBOARD_VIEW = 'dashboard.view';
// Manajemen pos
const POST_VIEW = 'post.view';
const POST_CREATE = 'post.create';
const POST_EDIT = 'post.edit';
const POST_DELETE = 'post.delete';
const POST_PUBLISH = 'post.publish';
// Manajemen topik
const TOPIC_VIEW = 'topic.view';
const TOPIC_CREATE = 'topic.create';
const TOPIC_EDIT = 'topic.edit';
const TOPIC_DELETE = 'topic.delete';
// Manajemen komentar
const COMMENT_VIEW = 'comment.view';
const COMMENT_CREATE = 'comment.create';
const COMMENT_EDIT = 'comment.edit';
const COMMENT_DELETE = 'comment.delete';
const COMMENT_MODERATE = 'comment.moderate';
// Manajemen pengguna
const USER_VIEW = 'user.view';
const USER_CREATE = 'user.create';
const USER_EDIT = 'user.edit';
const USER_DELETE = 'user.delete';
}
2. Sinkronkan Izin ke Database
Setelah mendefinisikan izin, kita perlu menyinkronkannya ke database:
php artisan laravolt:sync-permission
3. Buat Seeder Database untuk Peran
Buat seeder untuk menetapkan peran awal dan memberikan izin yang sesuai:
php artisan make:seeder AclSeeder
Perbarui seeder dengan definisi peran kita:
<?php
namespace Database\Seeders;
use App\Enums\Permission;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Artisan;
use Laravolt\Platform\Models\Role;
class AclSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// Buat peran
$admin = Role::firstOrCreate(['name' => 'Administrator']);
$writer = Role::firstOrCreate(['name' => 'Writer']);
$member = Role::firstOrCreate(['name' => 'Member']);
// Pastikan izin disinkronkan
Artisan::call('laravolt:sync-permission');
// Berikan semua izin kepada admin (wildcard)
$admin->syncPermission(['*']);
// Berikan izin tertentu kepada peran Penulis
$writer->syncPermission([
Permission::DASHBOARD_VIEW,
Permission::POST_VIEW,
Permission::POST_CREATE,
Permission::POST_EDIT,
Permission::POST_DELETE,
Permission::COMMENT_VIEW,
Permission::COMMENT_CREATE,
Permission::COMMENT_EDIT,
Permission::COMMENT_DELETE,
]);
// Berikan izin tertentu kepada peran Anggota
$member->syncPermission([
Permission::COMMENT_VIEW,
Permission::COMMENT_CREATE,
Permission::COMMENT_EDIT,
Permission::COMMENT_DELETE,
]);
}
}
4. Perbarui Seeder Database
Tambahkan AclSeeder kita ke seeder database utama:
<?php
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
$this->call([
AclSeeder::class,
]);
}
}
5. Buat Pengguna Uji Coba untuk Setiap Peran
Mari kita perbarui seeder kita untuk membuat pengguna uji coba untuk setiap peran:
php artisan make:seeder UserSeeder
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Hash;
class UserSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// Buat pengguna admin
Artisan::call('laravolt:admin Administrator [email protected] secret');
/** @var User */
$admin = User::query()->where('email', '[email protected]')->first();
$admin->assignRole('Administrator');
// Buat pengguna penulis
$writer = User::firstOrCreate(
['email' => '[email protected]'],
[
'name' => 'Content Writer',
'password' => Hash::make('secret'),
'status' => 'ACTIVE',
]
);
$writer->assignRole('Writer');
// Buat pengguna anggota
$member = User::firstOrCreate(
['email' => '[email protected]'],
[
'name' => 'Regular Member',
'password' => Hash::make('password'),
'status' => 'ACTIVE',
]
);
$member->assignRole('Member');
}
}
Jangan lupa untuk menambahkan seeder ini ke kelas DatabaseSeeder.php
juga.
<?php
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
$this->call([
AclSeeder::class,
UserSeeder::class,
]);
}
}
7. Jalankan Seeder
Sekarang kita dapat mengisi database kita dengan peran awal, izin, dan pengguna uji coba:
php artisan db:seed
Dengan pengaturan ini, kita telah menetapkan sistem peran dan izin lengkap untuk aplikasi portal berita kita menggunakan ACL Laravolt. Aplikasi ini sekarang memiliki tiga peran yang berbeda (Administrator, Penulis, dan Anggota), masing-masing dengan izin yang sesuai. Kami juga telah membuat pengguna uji coba untuk memudahkan pengujian selama pengembangan.
Simpan Perubahan
git add .
git commit -m "Setup database and ACL seeder"
Jaminan Kualitas
Untuk memastikan kode kita memenuhi standart kualitas sejak awal, kita akan mengatur PHPStan untuk analisis statis dan Laravel Pint untuk perbaikan gaya penulisan kode otomatis.
1. Instal Dependensi
composer require --dev phpstan/phpstan larastan/larastan spaze/phpstan-disallowed-calls laravel/pint
Setup PHPStan
2. Buat File Konfigurasi
Buat file phpstan.neon
di root proyek kita:
touch phpstan.neon
includes:
- ./vendor/larastan/larastan/extension.neon
- ./vendor/spaze/phpstan-disallowed-calls/extension.neon
parameters:
paths:
- app
- config
# The level 9 is the highest level
level: 5
treatPhpDocTypesAsCertain: false
disallowedFunctionCalls:
- function: 'env()'
message: 'use config() instead'
allowIn:
- config/*.php
3. Jalankan Analisis
./vendor/bin/phpstan analyse
Catatan: Pastikan perintah berjalan dengan baik dan tidak ada kesalahan yang terlewat. Apabila ada error, tambahkan option
--memory-limit=2G
. Jadi perintah yang harus dijalankan ialah:./vendor/bin/phpstan analyse --memory-limit=2G
Perbaiki masalah apa pun yang ditemukan PHPStan untuk memastikan kode kita memenuhi stkitar kualitas tinggi. Masalah umum meliputi:
- Deklarasi tipe yang hilang
- Metode yang tidak terdefinisi
- Akses nilai yang mungkin null
- Tipe yang tidak kompatibel dalam argumen
Setup GitHub Actions
Kita akan membuat 2 Job di GitHub Actions untuk menjalankan perbaikan otomatis gaya penulisan kode dan mengecek kualitas kode kita (PHPStan dan cakupan kode > 90%).
1. Code Style Fixes
Buat file .github/workflows/lint.yml
di root proyek kita:
mkdir -p .github/workflows
touch .github/workflows/lint.yml
name: Linting
on:
pull_request:
branches:
- develop
- main
permissions:
contents: write
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }} # This ensures we check out the PR branch
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Run Pint
run: vendor/bin/pint
- name: Commit Changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: 'fix: code style'
commit_options: '--no-verify'
branch: ${{ github.head_ref }} # Make sure changes are committed to the PR branch
2. Code Quality Check
Buat file .github/workflows/quality.yml
di root proyek kita:
touch .github/workflows/quality.yml
name: Tests
on:
push:
branches:
- develop
- main
pull_request:
branches:
- develop
- main
jobs:
ci:
runs-on: ubuntu-latest
container:
image: ramaid/image:php8.4-fullstack-cli-v2.5.0
options: --user root
volumes:
- /run/docker:/run/docker
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Fetch all history for all branches and tags
fetch-depth: 0
- name: Install Dependencies
run: composer install --no-interaction --prefer-dist --optimize-autoloader
- name: Setup Environment
run: |
cp .env.example .env
php artisan migrate --seed --force
php artisan key:generate
php artisan laravolt:link
- name: Static Analysis
run: vendor/bin/phpstan analyse
- name: Tests
run: |
XDEBUG_MODE=coverage php artisan test --coverage \
--coverage-clover=coverage.xml \
--log-junit=results.xml
# - name: SonarCloud Scan
# uses: SonarSource/sonarqube-scan-action@v5
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# - name: Sonar Scan Self Hosted
# env:
# SONAR_TOKEN: ${{ secrets.SONAR_MC_TOKEN }}
# run: |
# sonar-scanner -Dsonar.token=$SONAR_TOKEN -Dsonar.host.url=http://sonar.malescast.tech/
Langkah Selanjutnya
Panduan implementasi di atas mencakup pengaturan awal struktur database, model, dan kebijakan otorisasi untuk portal berita kita. Pada bagian selanjutnya dari tutorial ini (yang akan segera ditambahkan), kita akan membahas:
- Menyiapkan AutoCRUD untuk panel admin
- Membangun situs web yang dihadapi publik dengan TailwindCSS
- Mengimplementasikan sistem komentar
- Membuat grafik dasbor dengan Laravolt Chart
- Mengembangkan fitur-fitur yang lebih canggih seperti ekspor dan penyaringan
- Menambahkan notifikasi email
- Mengimplementasikan pengaturan situs web dan pengalihan tema
- Mengoptimalkan kinerja dan kualitas