New Laravel Project & Laravel Mix

New Laravel Project & Laravel Mix
เริ่มใช้งาน Laravel (v.8) + install stater tool – *** TEST หลายรอบแล้ว ว่า OKAY ***
-> ติดตั้ง Laravel ด้วย composer – สร้างโปรเจ็ตต์ ชื่อ laravel-test-app

ตอนติดตั้ง เข้าใจว่า composer มันตรวจสอบก่อนแล้วว่าเรามี php version อะไรอยู่ใน path ของเรา ถ้าเจอ version เก่าๆหน่อย มันจะไม่เอา Laravel v.10 v.11 มาให้เราเลย (มั้ง) – จนถึงตอนนี้เลยยังได้ใช้แต่ v.8 เท่านั้น

composer create-project --prefer-dist laravel/laravel laravel-test-app
cd laravel-test-app
-> ใช้งาน Bootstrap UI / Bootstrap UI auth
1.  **ติดตั้ง `laravel/ui`:**
composer require laravel/ui
2.  **สร้าง Bootstrap Scaffolding:**
php artisan ui bootstrap --auth
* `--auth` จะสร้างระบบ login/register ให้ด้วย ซึ่งสะดวกต่อการใช้งาน
3.  **ติดตั้ง Dependencies ฝั่ง Frontend:**
npm install
4.  **คอมไพล์ Assets:**
npm run dev

run Mix อีกรอบ

คราวนี้ Warning เยอะแยะ แต่เหมือนจะไม่มีปัญหาอะไร

-> ติดตั้ง debug bar / sweetalert2 / axios (ปรกติมีอยู่แล้ว) / tabulator / lightbox2 /

axios ได้มาแล้ว ไม่ต้องลงเพิ่ม

ติดตั้ง debugbar

composer require barryvdh/laravel-debugbar –dev

ถ้าลืมใส่ –dev มันจะถามเราอีกรอบ

ใช้ npm เพื่อติดตั้ง JavaScript libraries

npm install tabulator-tables sweetalert2 lightbox2
-> ติดตั้ง special library เช่น phpoffice-phpspreadsheet / chart.js
ใช้ Composer เพื่อติดตั้ง library สำหรับจัดการไฟล์ Excel

composer require phpoffice/phpspreadsheet 
npm install chart.js

ใช้ composer require – เพราะ Library ตัวนี้เป็น PHP – เอาไว้ใช้งาน Backend

ใช้ npm – เพราะ Library ตัวนี้เป็น Javascript – เอาไว้ทำงาน Frontend

-> compile using mix

ก่อน compile ก็ต้องเรียก Library ที่ต้องการเข้ามาก่อน แล้วค่อย compile เพื่อสร้าง public app.js & app.css

การ add code javascript ลงไปที่ resource app.js

พอเรา run mix เพื่อ compile มันก็เหมือนการซ่อน code ของเราเข้าไปในตัว

-> test page

สร้าง controller

    **สร้าง Controller:**
    รันคำสั่ง Artisan เพื่อสร้าง Controller ใหม่ชื่อ `TestPageController`

    php artisan make:controller TestPageController
        // แสดงหน้าเว็บหลัก
        public function index()
        {
            $sampleData = [
                ['id' => 1, 'name' => 'Oli Bob', 'location' => 'United Kingdom', 'gender' => 'male', 'rating' => 1, 'col' => 'red'],
                ['id' => 2, 'name' => 'Mary May', 'location' => 'Germany', 'gender' => 'female', 'rating' => 2, 'col' => 'blue'],
                ['id' => 3, 'name' => 'Christine Lobowski', 'location' => 'France', 'gender' => 'female', 'rating' => 0, 'col' => 'green'],
                ['id' => 4, 'name' => 'Brendon Philips', 'location' => 'USA', 'gender' => 'male', 'rating' => 1, 'col' => 'orange'],
            ];

            return view('testpage', ['tableData' => json_encode($sampleData)]);
        }
        // สำหรับ Export Excel

        use PhpOffice\PhpSpreadsheet\Spreadsheet;
        use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

        public function export()
        {
            $spreadsheet = new Spreadsheet();
            $sheet = $spreadsheet->getActiveSheet();
            $sheet->setCellValue('A1', 'Hello World !');

            $writer = new Xlsx($spreadsheet);

            // เตรียม Header สำหรับการดาวน์โหลด
            $fileName = 'hello_world.xlsx';
            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
            header('Content-Disposition: attachment; filename="'. $fileName .'"');
            header('Cache-Control: max-age=0');

            $writer->save('php://output');
        }

สร้าง view

resources/views/testpage.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Laravel Test Page</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container mt-5">
        <h1 class="mb-4">🚀 ทดสอบการติดตั้ง Packages</h1>

        <div class="alert alert-primary" role="alert">
            <b>Bootstrap 5:</b> ติดตั้งสมบูรณ์! นี่คือตัวอย่าง Alert Component.
        </div>

        <div class="mb-4">
            <button id="sweetalert-btn" class="btn btn-success">
                <b>SweetAlert2:</b> คลิกเพื่อทดสอบ
            </button>
        </div>

        <div class="mb-4">
                <a href="{{ route('export.excel') }}" class="btn btn-info">
                <b>PhpSpreadsheet:</b> คลิกเพื่อดาวน์โหลด Excel
            </a>
        </div>

        <div class="card mb-4">
            <div class="card-header">
                <b>Tabulator:</b> ตารางข้อมูลด้านล่างนี้สร้างโดย Tabulator
            </div>
            <div class="card-body">
                <div id="example-table" data-tabledata="{{ $tableData }}"></div>
            </div>
        </div>

        <div class="card">
            <div class="card-header">
                <b>Lightbox2:</b> คลิกที่รูปภาพเพื่อดูขนาดเต็ม
            </div>
            <div class="card-body">
                <div class="row">
                    <div class="col-md-3">
                        <a href="{{ asset('images/full1.jpg') }}" data-lightbox="gallery" data-title="Image 1">
                            <img src="{{ asset('images/thumb1.jpg') }}" class="img-thumbnail">
                        </a>
                    </div>
                    <div class="col-md-3">
                        <a href="{{ asset('images/full2.jpg') }}" data-lightbox="gallery" data-title="Image 2">
                            <img src="{{ asset('images/thumb2.jpg') }}" class="img-thumbnail">
                        </a>
                    </div>
                </div>
            </div>
        </div>

    </div>
    <script src="{{ asset('js/app.js') }}"></script>
    
</body>
</html>

การสร้าง table data จะดูยากหน่อย – Controller Test Page จะสร้าง Data ขึ้นมา (manual หรือ จาก DB) แล้วส่งมาให้ VIEW – ในส่วน VIEW เมื่อได้แล้ว ไม่ได้แสดงผล แต่หมก Data ไว้ใน attribute ซักที่หนึ่ง – ทีนี้ เราก็เขียน Javascript ที่ทำงาน ตอน DomContentLoaded ซึ่งก็คือโหลดหน้าตา component มาหมดแล้ว โดย JS จะค้นหา Div ที่จะแสดงผล, ค้าหา Data ที่หมกเอาไว้, จากนั้นสร้าง Tabulator table ใส่ column definition – แปะ Data แล้ว มันก็แสดงผลใน Div นั้น

แต่พอดี Javascript นี้ เราสร้าง ใน app.js แล้ว compile ไปตั้งแต่แรก

หลังจาก compile เราก็เอามันมา attached ด้วย asset(‘app.js’)

เพิ่ม route

    use App\Http\Controllers\TestPageController;

    Route::get('/test-page', [TestPageController::class, 'index'])->name('test.page');
    Route::get('/export-excel', [TestPageController::class, 'export'])->name('export.excel');

run serve

จะใช้ lightbox2 ต้องมี jQuery ก่อน

เหมือนว่า jQuery ไม่ได้โหลดมาตั้งแต่แรก – ไม่ค่อยใช้กันแล้ว?

npm run dev เพื่อ compile mix ใหม่

สร้าง ห้อง images ใน public folder

เพิ่มไฟล์ full1.jpg full2.jpg thumb1.jpg thumb2.jpg

ถ้า lightbox2 ทำงาน เราจะเห็นว่าเวลา click ที่ภาพก็จะมี popup show ขึ้นมา

เจอปัญหาว่าปุ่มมันหายไป ทั้งที่ตัวปุ่มก็ถูก copy ไปวางตั้งแต่ตอน compile mix แล้ว

สร้าง พื้นที่แสดงกราฟ

            <div class="card mb-4">
            <div class="card-header">
                ตัวอย่างกราฟวงกลม (Pie Chart)
            </div>
            <div class="card-body">
                {{-- 1. สร้าง Canvas สำหรับวาดกราฟ --}}
                <canvas id="myPieChart" width="100%" height="50"></canvas>
            </div>
            <div class="card-footer small text-muted">
                อัปเดตเมื่อ: {{ now()->format('d/m/Y H:i') }}
            </div>
        </div>

เพิ่ม code การแสดงผล ลงใน app.js

require('./bootstrap');

// Import Libraries
const Swal = require('sweetalert2');
const Tabulator = require('tabulator-tables');

// เรียกใช้ Lightbox2 หลังจาก bootstrap.js
require('lightbox2');

import Chart from 'chart.js/auto';
window.Chart = Chart; // ทำให้เรียกใช้จากที่ไหนก็ได้

// 1. SweetAlert2 Initialization
// ต้องแน่ใจว่า element `sweetalert-btn` ถูกโหลดในหน้าเว็บแล้ว
document.addEventListener('DOMContentLoaded', function () {
    const sweetAlertBtn = document.getElementById('sweetalert-btn');
    if (sweetAlertBtn) {
        sweetAlertBtn.addEventListener('click', () => {
            Swal.fire({
                title: 'สำเร็จ!',
                text: 'SweetAlert2 ทำงานบน Laravel Mix แล้ว!',
                icon: 'success',
                confirmButtonText: 'ยอดเยี่ยม'
            });
        });
    }

    // 2. Tabulator Initialization
    // ดึงข้อมูลจาก Blade ผ่าน tag script
    const exampleTable = document.getElementById('example-table');
    if (exampleTable) {
        const tableData = JSON.parse(exampleTable.getAttribute('data-tabledata'));

        new Tabulator("#example-table", {
            data: tableData,
            layout: "fitColumns",
            columns: [
                { title: "Name", field: "name", width: 200 },
                { title: "Location", field: "location", hozAlign: "left" },
                { title: "Gender", field: "gender", hozAlign: "center" },
                { title: "Color", field: "col", hozAlign: "center" },
            ],
        });
    }

    const ctx = document.getElementById('myPieChart');
    // 3. ข้อมูลและตัวเลือกสำหรับกราฟ
    const myPieChart = new Chart(ctx, {
        type: 'pie', // ประเภทกราฟ
        data: {
            labels: [ // ป้ายกำกับของแต่ละชิ้น
                'ฝ่ายขาย',
                'การตลาด',
                'IT',
                'บัญชี'
            ],
            datasets: [{
                label: 'งบประมาณฝ่าย',
                data: [300, 50, 100, 75], // ข้อมูลตัวเลข
                backgroundColor: [ // สีของแต่ละชิ้น
                    'rgb(255, 99, 132)',
                    'rgb(54, 162, 235)',
                    'rgb(255, 205, 86)',
                    'rgb(75, 192, 192)'
                ],
                hoverOffset: 4
            }]
        },
        options: {
            responsive: true, // ทำให้กราฟปรับขนาดตามหน้าจอ
            plugins: {
                legend: {
                    position: 'top', // แสดงป้ายกำกับไว้ด้านบน
                },
                title: {
                    display: true,
                    text: 'สัดส่วนงบประมาณของแต่ละฝ่าย' // หัวข้อของกราฟ
                }
            }
        }
    });
});

เมื่อแก้ไข app.js (ใน resources) ก็ต้อง compile ให้เป็น app.js (ใน public) ก่อน จากนั้นก็โหลดขึ้นมาดู

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *