分類: 筆記x備忘

  • Visual Studio Code 的 PHP CS Fixer 設定

    Visual Studio Code 的 PHP CS Fixer 設定

    最近有幸換一台好一點電腦,開始投入 VSCode 的懷抱,轉換總是陣痛一波波襲來,於是趕緊記錄下來。希望能對以後使用 VSCode 的 PHPer 排版有幫助。

    PHP CS Fixer 是一個自動格式化 PHP 程式碼,利用這個外掛達到達到 PHP 統一風格的效果。


    版本:

    PHP CS Fixer 3.73.1 Persian Successor by Fabien Potencier, Dariusz Ruminski and contributors.

    PHP runtime: 8.2.28


    PHP CS Fixer 安裝與設定

    1. 安裝 PHP CS Fixer

    你有兩種主要安裝方式:透過 Composer 全域安裝或下載 phar 檔案。以下以 Composer 全域安裝為例:

    1. 確保 Composer 已安裝

    如果尚未安裝 Composer,請至 Composer 官方網站 下載並安裝。

    2. 全域安裝 PHP CS Fixer

    開啟終端機(Terminal),執行下列指令:

    composer global require friendsofphp/php-cs-fixer

    安裝完成後,透過以下指令確認執行檔路徑:

    composer global config bin-dir --absolute

    例如,你可能會得到 /Users/yourname/.composer/vendor/bin。記下這個路徑,因為稍後在 VSCode 或命令列使用時需要指定。

    注意兩點:

    1. 注意 Composer / PHP 的路徑和權限。可能會遇到執行權限不足的問題。
    2. 注意 User 的路徑名稱,這邊統一用 yourname 代替。

    2. 建立 PHP CS Fixer 設定檔

    我們提供以下最新版的 config.php 設定檔範例,此檔案包含多項格式化規則(例如 PSR、Symfony 規範),並採用新版語法。請將此檔案存放在你希望統一管理格式化規則的位置,例如 ~/.config/php-cs-fixer/config.php。

    小提醒,註解我是用 AI 生成的。裡面設定得依照需求和團隊規範來調整。

    <?php
    
    $header = <<<'EOF'
    This file is part of PHP CS Fixer.
    
    (c) Fabien Potencier <[email protected]>
        Dariusz Rumiński <[email protected]>
    
    This source file is subject to the MIT license that is bundled
    with this source code in the file LICENSE.
    EOF;
    
    $finder = PhpCsFixer\Finder::create()
        ->exclude('tests/Fixtures') // 排除特定目錄
        ->in(__DIR__) // 設定要檢查的目錄
    ;
    
    $config = (new PhpCsFixer\Config())
        ->setRiskyAllowed(true) // 允許使用可能具有風險的規則
        ->setRules([
            // '@PHP56Migration' => true, // PHP 5.6 的語法遷移規則集(已註解掉)
            '@PHPUnit60Migration:risky'   => true, // 適用於 PHPUnit 6.0 的遷移規則(風險規則)
            '@PSR1'                       => true, // 遵循 PSR-1 基本編碼標準
            '@PSR2'                       => true, // 遵循 PSR-2 編碼風格指南
            '@Symfony'                    => true, // 遵循 Symfony 的編碼標準
            '@Symfony:risky'              => true, // Symfony 的風險規則集
            'align_multiline_comment'     => true, // 將多行註解對齊
            'array_indentation'           => true, // 陣列的縮排規則
            'array_syntax'                => ['syntax' => 'short'], // 使用短陣列語法
            'blank_line_before_statement' => true, // 在特定語句前插入空行
            'binary_operator_spaces'      => [ // 二元運算符的空格規則
                'operators' => [
                    '=>' => 'align', // 將 `=>` 對齊
                    '='  => 'single_space', // `=` 使用單一空格
                ],
            ],
            'combine_consecutive_issets'   => true, // 合併連續的 `isset` 語句
            'combine_consecutive_unsets'   => true, // 合併連續的 `unset` 語句
            'comment_to_phpdoc'            => true, // 將普通註解轉換為 PHPDoc
            'compact_nullable_typehint'    => true, // 使用緊湊的 nullable 類型提示語法
            'concat_space'                 => ['spacing' => 'one'], // 字串連接符號使用單一空格
            'escape_implicit_backslashes'  => true, // 轉義隱式的反斜線
            'explicit_indirect_variable'   => true, // 明確的間接變數語法
            'explicit_string_variable'     => true, // 明確的字串變數語法
            'final_internal_class'         => true, // 將內部類標記為 final
            'fully_qualified_strict_types' => true, // 使用完全限定的類型名稱
            'function_to_constant'         => ['functions' => ['get_class', 'get_called_class', 'php_sapi_name', 'phpversion', 'pi']], // 將特定函數轉換為常數
            // 'header_comment' => ['header' => $header], // 添加檔案頭部註解(已註解掉)
            'heredoc_to_nowdoc'                             => true, // 將 heredoc 轉換為 nowdoc
            'increment_style'                               => false, // 遞增/遞減運算符的風格
            'list_syntax'                                   => ['syntax' => 'short'], // 使用短語法的 list
            'logical_operators'                             => true, // 使用邏輯運算符 `and`, `or`, `xor` 替代符號
            'method_argument_space'                         => ['on_multiline' => 'ensure_fully_multiline'], // 方法參數的空格規則
            'method_chaining_indentation'                   => true, // 方法鏈式調用的縮排
            'multiline_comment_opening_closing'             => true, // 多行註解的開頭和結尾格式化
            'no_alternative_syntax'                         => true, // 禁用替代語法(如 `endif`)
            'no_binary_string'                              => true, // 禁用二進位字串語法
            'no_extra_blank_lines'                          => ['tokens' => ['break', 'continue', 'extra', 'return', 'throw', 'use', 'parenthesis_brace_block', 'square_brace_block', 'curly_brace_block']], // 移除多餘的空行
            'no_null_property_initialization'               => true, // 移除屬性初始化為 null
            'echo_tag_syntax'                               => ['format' => 'long'], // 使用長格式的 echo 標籤
            'no_superfluous_elseif'                         => true, // 移除多餘的 elseif
            'no_unneeded_curly_braces'                      => true, // 移除不必要的大括號
            'no_unneeded_final_method'                      => true, // 移除不必要的 final 方法
            'no_unreachable_default_argument_value'         => true, // 移除無法到達的默認參數值
            'no_unset_on_property'                          => true, // 禁止對屬性使用 unset
            'no_useless_else'                               => true, // 移除無用的 else
            'no_useless_return'                             => true, // 移除無用的 return
            'ordered_class_elements'                        => true, // 排序類的元素
            'ordered_imports'                               => true, // 排序 import 語句
            'php_unit_internal_class'                       => true, // PHPUnit 的內部類應標記為 final
            'phpdoc_order_by_value'                         => ['annotations' => ['covers']], // 按值排序 PHPDoc 的註解
            'php_unit_set_up_tear_down_visibility'          => true, // 設置 PHPUnit 的 setUp/tearDown 方法的可見性
            'php_unit_strict'                               => true, // 使用 PHPUnit 的嚴格模式
            'php_unit_test_annotation'                      => true, // 強制使用 PHPUnit 的 @test 註解
            'php_unit_test_case_static_method_calls'        => ['call_type' => 'this'], // 使用 `$this` 調用靜態方法
            'php_unit_test_class_requires_covers'           => true, // 強制測試類需要 @covers 註解
            'phpdoc_add_missing_param_annotation'           => true, // 添加缺失的 @param 註解
            'phpdoc_order'                                  => true, // 排序 PHPDoc 的標籤
            'phpdoc_trim_consecutive_blank_line_separation' => true, // 修剪 PHPDoc 中的連續空行
            'phpdoc_types_order'                            => true, // PHPDoc 類型排序
            'return_assignment'                             => false, // 避免直接返回賦值
            'semicolon_after_instruction'                   => true, // 在指令後添加分號
            'single_line_comment_style'                     => true, // 單行註解的風格
            'strict_comparison'                             => false, // 使用嚴格比較
            'strict_param'                                  => false, // 使用嚴格參數
            'string_line_ending'                            => true, // 字串行結尾一致
            'ternary_operator_spaces'                       => true, // 三元運算符的空格規則
            'trim_array_spaces'                             => true, // 修剪陣列中的多餘空格
            'unary_operator_spaces'                         => true, // 一元運算符的空格規則
            'yoda_style'                                    => true, // 使用 Yoda 條件風格
            'whitespace_after_comma_in_array'               => true, // 陣列中逗號後的空格
        ])
        ->setFinder($finder)
    ;
    
    // special handling of fabbot.io service if it's using too old PHP CS Fixer version
    if (false !== getenv('FABBOT_IO')) {
        try {
            PhpCsFixer\FixerFactory::create()
                ->registerBuiltInFixers()
                ->registerCustomFixers($config->getCustomFixers())
                ->useRuleSet(new PhpCsFixer\RuleSet($config->getRules()));
        } catch (PhpCsFixer\ConfigurationException\InvalidConfigurationException $e) {
            $config->setRules([]);
        } catch (UnexpectedValueException $e) {
            $config->setRules([]);
        } catch (InvalidArgumentException $e) {
            $config->setRules([]);
        }
    }
    
    return $config;

    3. 配置與使用

    (1) 測試設定檔是否正常運作

    在終端機中執行以下指令,檢查格式化是否能正常運作:

    php-cs-fixer fix --config=/Users/yourname/.config/php-cs-fixer/config.php --dry-run --diff

    若顯示格式化差異且無錯誤訊息,代表設定檔運作正常。

    (2) 在 VSCode 中整合使用

    若你在 VSCode 中進行開發,請依下列步驟進行設定:

    1. 安裝 VSCode PHP CS Fixer 擴充套件

    可從 VSCode 擴充功能市場搜尋並安裝例如 junstyle.php-cs-fixer 之類的擴充套件。

    2. 設定 VSCode 使用全域 PHP CS Fixer

    在 VSCode 的 settings.json 中加入下列設定,指定執行檔路徑與全域設定檔位置:

    {
        "php-cs-fixer.executablePath": "/Users/yourname/.composer/vendor/bin/php-cs-fixer",
        "php-cs-fixer.config": "/Users/yourname/.config/php-cs-fixer/config.php",
        "editor.formatOnSave": true,
        "[php]": {
            "editor.defaultFormatter": "junstyle.php-cs-fixer"
        }
    }

    ※ 請依據實際路徑修改 “php-cs-fixer.executablePath” 的內容。

    3. 測試 VSCode 格式化功能

    開啟一個 PHP 檔案,嘗試保存(Save),檢查程式碼是否依照設定自動格式化。

    4. 設定檔內容說明

    這份設定檔主要包含以下部分:

    Header 字串:定義了版權和授權說明,雖然目前透過 header_comment 規則被註解掉,但可根據需求啟用。

    Finder 設定:透過 PhpCsFixer\Finder 指定排除某些目錄(例如 tests/Fixtures),並指定掃描路徑(使用 __DIR__)。

    Config 物件:利用 (new PhpCsFixer\Config()) 建立設定物件,並透過 setRules 指定各項格式化規則,例如 PSR、Symfony、單行註解、縮排、運算子對齊等。

    特別注意:

    • 將原本已被移除的規則集(如 @PHP56Migration)註解掉。

    • 對於已重命名的規則,例如 no_short_echo_tag 改為 echo_tag_syntax,並依新規範提供相應配置。

    • binary_operator_spaces 的設定改為使用 operators 陣列,設定 => 為 align,而 = 為 single_space。

    特殊處理:針對 fabbot.io 等可能使用較舊版 PHP CS Fixer 的服務,透過 try/catch 機制進行相容性處理。


    總結

    按照以上步驟完成安裝、設定檔建立及 VSCode 整合後,你就能使用這份統一的 PHP CS Fixer 設定來自動格式化 PHP 程式碼,確保程式碼風格的一致性與可讀性。若有需要進一步調整規則,可以參考 PHP CS Fixer 官方文件 進行自訂。

  • MacOS 添加本地伺服器的 DNS

    MacOS 添加本地伺服器的 DNS

    目前本地開發使用 VM 的應用程式(VMWare 或 Parallels),也會需要將 local 的 domain 指向正確的 Private IP。原本都是用 iHost 這套 GUI APP ,這 APP 實作修改 /etc/hosts 的方式達到顯示 local domain 的功能,但有兩個問題:

    1. /etc/hosts 的權限是 root 導致每次開啟的時候都需要操作更換權限。
    2. 沒有支援 wildcard 的功能

    於是我想換一個方法處理。可惜的是目前還沒找到 GUI 的 APP,這邊實作在 macOS 上使用 Homebrew 安裝 dnsmasq ,配置讓所有 *.localhost.test 指向 10.211.55.12 :


    1. 安裝 dnsmasq

    如果尚未安裝 Homebrew,可以先到 Homebrew 官網 參考安裝方法。安裝好 Homebrew 後,打開終端機執行:

    brew install dnsmasq

    2. 配置 dnsmasq

    編輯 dnsmasq 的配置文件 /usr/local/etc/dnsmasq.conf,加入對 *.localhost.test 的解析規則(注意這路徑未必正確):

    nano /usr/local/etc/dnsmasq.conf

    在文件中新增以下這一行:

    address=/.localhost.test/10.211.55.12

    這條規則表示所有以 localhost.test 為後綴的域名(例如 abc.localhost.test)都會被解析到 10.211.55.12。


    3. 啟動 dnsmasq 服務

    配置完成後,啟動 dnsmasq 並設置為開機自啟:

    brew services start dnsmasq

    如果之後有修改配置,需要重啟服務:

    brew services restart dnsmasq

    4. 配置 macOS 使用本地 dnsmasq

    為了使 macOS 對 localhost.test 域名的 DNS 查詢走本地的 dnsmasq,需要在 /etc/resolver 目錄下建立解析器文件。

    1. 先建立 /etc/resolver 目錄(如果尚不存在):

    sudo mkdir -p /etc/resolver

    2. 創建一個名為 localhost.test 的文件:

    sudo nano /etc/resolver/localhost.test

    在文件中加入:

    nameserver 127.0.0.1

    這樣,所有針對 *.localhost.test 的 DNS 請求都會由本地的 dnsmasq(監聽 127.0.0.1)來處理。


    5. 測試配置

    可以使用 dig 或 nslookup 測試解析是否正確。例如,執行:

    dig subdomain.localhost.test

    查詢結果應該會顯示 IP 為 10.211.55.12。

    以上步驟是用 AI 寫的,需要特別注意

    /usr/local/etc/dnsmasq.conf 這個路徑未必是正確的,安裝完成後提示:

    To start dnsmasq now and restart at startup:
      sudo brew services start dnsmasq
    Or, if you don't want/need a background service you can just run:
      /opt/homebrew/opt/dnsmasq/sbin/dnsmasq --keep-in-foreground -C /opt/homebrew/etc/dnsmasq.conf -7 /opt/homebrew/etc/dnsmasq.d,\*.conf
    ==> Summary
    🍺  /opt/homebrew/Cellar/dnsmasq/2.91: 11 files, 665.1KB
    ==> Running `brew cleanup dnsmasq`...

    所以設定的路徑是 /opt/homebrew/etc/dnsmasq.conf

    這樣之後 VM 統一設定網域 localhost.test 或子網域就能運作啦!

  • Mac 上使用 pyenv 管理 python 環境

    Mac 上使用 pyenv 管理 python 環境

    先說可能用 docker 會很方便,這邊先不考慮延伸管理以及效能等問題,採用原生的方式處理。

    這裡記錄一下久久用一次很容易忘記的操作情境。

    安裝和設定,這通常只需要處理一次。需要注意設定的目標檔案,這裡使用的是 .bashrc ,有可能是
    .bash_profile 或是 .zshrc,也可以直接開啟檔案寫入:

    # 安裝
    brew install pyenv
    # 設定
    echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
    echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(pyenv init -)"' >> ~/.bashrc

    查看有安裝哪些版本,他將會列出目前有的版本以及設定的名稱:

    pyenv versions

    安裝指定版本,版本名稱有很多,建議安裝前先查一下:

    # 列出可安裝的版本
    pyenv install -l
    # 安裝指定版本
    pyenv install miniconda3-4.3.11

    設定全域的版本,這樣只要該資料夾沒有指定版本就會預設全域的版本。

    pyenv global 3.7.4

    查看現在是使用什麼版本

    python -V

    最常做的是指定某個資料夾版本,使用 local 指令,可以建立在該資料夾內的版本號

    python local 3.7.4

    建立一個虛擬環境,當我們有安裝一些套件等,建議為這個環境命名,這樣多的不同應用環境的專案比較好獨立運作,不會互相干擾環境也不容易髒掉。

    pyenv virtualenv 3.7.4 testenv

    如此一來呼叫 versions 指令時就會多出 testenv 這個環境啦!

    以上。

  • 實作 js 函式庫包裝為 API 提供給後端呼叫

    實作 js 函式庫包裝為 API 提供給後端呼叫

    最近在想有滿多 js 實作資料處理的函式庫,於是想看有沒有 nodejs 或是相似的程式語言可以相容 js 實做包裝城後端,於是想到了用 Cloudflare Worker 服務來實作。

    我拿 iztro 這套服務來實作,我認為很適合包裝成 API 呼叫的功能有幾個特色:

    1. 以處理、整理資料為目的的服務。
    2. 不需要相依其他套件( e.g. jQuery)
    3. 產生的結果是一包字串(json, xml 等),或是能轉成 base64 的檔案字串。

    先附上 Github repo 。名字叫做「My Iztro Worker」,有夠隨便,哈。

    這個服務基於 Cloudflare Worker 實作,實作以下功能:

    • API 服務:接受包含生日、出生時間、性別等參數的 HTTP GET 請求,返回相應的紫微斗數資訊。
    • 使用說明頁面:當請求缺少必要參數時,返回一個包含 API 使用說明和測試表單的 HTML 頁面,方便使用者瞭解如何使用該 API。
    • 速率限制:為了防止濫用,對每個客戶端 IP 設置了每分鐘最多 10 次請求的限制。

    實作了一個 usage.js 頁面作為測試 form 表,並且使用 Worker 特有的功能實作呼叫頻率的限制;src/index.js 中可以依照原始套件的說明參考修改。

    部署方式請參考請參考原始碼的 README,我作了一個線上範例,視狀況可能會停用,且用且珍惜:


    同場加映,請 AI 協助生成實作 nodejs 的說明:

    將 JavaScript 函式庫包裝為 API,提供後端呼叫,是現代軟體開發中常見的需求。這種方法能夠將複雜的邏輯封裝起來,透過標準化的介面供其他應用程式或服務使用。以下是實作此項目的簡要流程:

    1. 選擇適當的執行環境: 首先,選擇一個適合執行 JavaScript 的環境。Node.js 是一個常見的選擇,因為它允許在伺服器端執行 JavaScript。此外,像 Cloudflare Workers 這樣的伺服器無關環境也提供了在邊緣節點執行 JavaScript 的能力。
    2. 建立專案結構: 為您的 API 建立一個新的專案目錄,並初始化專案:
       mkdir my-js-api
       cd my-js-api
       npm init -y

    這將建立一個包含預設設定的 package.json 檔案。

    1. 安裝相依套件: 根據您的需求,安裝必要的相依套件。例如,若您需要處理 HTTP 請求,可以安裝 Express.js:
       npm install express
    1. 撰寫 API 邏輯: 在專案目錄中,建立一個主檔案(例如 index.js),並撰寫處理 HTTP 請求的邏輯。以下是一個使用 Express.js 的簡單範例:
       const express = require('express');
       const app = express();
       const port = 3000;
    
       // 引入您的 JavaScript 函式庫
       const myLibrary = require('./myLibrary');
    
       app.use(express.json());
    
       app.post('/api/your-endpoint', (req, res) => {
         const input = req.body.input;
         const result = myLibrary.yourFunction(input);
         res.json({ result });
       });
    
       app.listen(port, () => {
         console.log(`API 伺服器正在 http://localhost:${port} 上運行`);
       });

    在這個範例中,我們建立了一個 POST 端點 /api/your-endpoint,接受 JSON 格式的請求,並使用 myLibrary 中的函式處理輸入。

    1. 測試 API: 在本機運行您的 API 伺服器,並使用工具(如 Postman)或命令列工具(如 curl)進行測試:
       curl -X POST http://localhost:3000/api/your-endpoint -H "Content-Type: application/json" -d '{"input": "your data"}'

    確保您的 API 能夠正確處理請求並返回預期的結果。

    1. 部署 API: 根據您的需求,將 API 部署到適當的環境中。例如,您可以將其部署到雲端服務提供商(如 AWS、Heroku)或使用 Docker 容器進行部署。
    2. 實作速率限制和安全性: 為了防止濫用,建議實作速率限制機制。此外,確保您的 API 僅允許授權的請求,並實作適當的驗證和授權機制。

    透過上述步驟,您可以將 JavaScript 函式庫包裝為 API,供後端系統呼叫,實現功能的模組化和重用性。

  • MacOS 上將指定資料夾內檔案繁體轉簡體

    MacOS 上將指定資料夾內檔案繁體轉簡體

    因為有案子需要簡繁轉換,除了精確的用詞轉換之外,需要先有一個初步的字體修改,以下提供 OpenCC + Python 作法,先說注意事項:

    1. Mac 上如果已經安裝 pyenv 工具,記得在指定資料夾內把 pyenv local 設定好,這次使用的 python 版本是 3.7.4 。
    2. 程式碼中需要設定 target_folder 和 file_extension 變數,作為資料夾路徑和要變更結尾的副檔名。如果有需求請更為從外部輸入。
    3. 使用 cmd 觸發執行,基本上就是一個工程師小工具。

    在 macOS 上,您可以使用腳本來批次將資料夾內指定副檔名的檔案從繁體中文轉為簡體中文。以下是解決方案的步驟:

    使用 Python 和 OpenCC

    我們將使用 Python 和 OpenCC 庫來完成繁簡轉換。

    1. 安裝必要工具

    1. 安裝 Python
      macOS 通常自帶 Python,但建議使用 Homebrew 安裝最新版: brew install python
    2. 安裝 OpenCC
      使用 pip 安裝 OpenCC: pip install opencc

    2. 建立批次轉換腳本

    以下是 Python 腳本範例:

    import os
    from opencc import OpenCC
    
    # 初始化 OpenCC
    cc = OpenCC('t2s')  # 繁體轉簡體配置
    
    # 設定目標資料夾路徑與副檔名
    target_folder = "/path/to/your/folder"  # 替換為您的資料夾路徑
    file_extension = ".txt"  # 指定需要處理的副檔名
    
    def convert_file_to_simplified(filepath):
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                content = f.read()
            # 進行繁簡轉換
            simplified_content = cc.convert(content)
            with open(filepath, 'w', encoding='utf-8') as f:
                f.write(simplified_content)
            print(f"轉換完成: {filepath}")
        except Exception as e:
            print(f"處理檔案時發生錯誤: {filepath},錯誤訊息: {e}")
    
    # 遍歷目標資料夾中的所有檔案
    for root, dirs, files in os.walk(target_folder):
        for file in files:
            if file.endswith(file_extension):
                full_path = os.path.join(root, file)
                convert_file_to_simplified(full_path)

    3. 執行腳本

    1. 將上述腳本存為 convert_to_simplified.py
    2. 使用終端機執行腳本: python3 convert_to_simplified.py

    4. 說明

    • 替換 target_folder 為您的資料夾路徑。
    • 如果處理其他副檔名,將 file_extension 的值改為相應的副檔名(例如 .md)。
    • 腳本會遍歷資料夾和子資料夾中的所有符合條件的檔案。

    使用者界面工具選擇

    如果您不熟悉編程,可以考慮使用支持繁簡轉換的文字編輯器,例如:

    • Sublime Text: 安裝相關插件進行批次轉換。
    • OpenCC GUI: 下載圖形化工具版本進行手動處理。

    以上。

  • 解決 PHP 的 dompdf 中文字體亂碼的方法

    解決 PHP 的 dompdf 中文字體亂碼的方法

    記錄一下一個之前解決過的問題。

    在使用 php 的 dompdf 會有中文字無法正確讀取的問題,這主要是字型的關係,官方有提供一個解決方法。

    先說什麼是 dompdf 請參考開源程式說明

    Dompdf 是一個 HTML 到 PDF 轉換器

    從本質上講,dompdf(主要)是一個用 PHP 編寫的、符合CSS 2.1 的HTML 佈局和渲染引擎。它是一個樣式驅動的渲染器:它將下載並讀取外部樣式表、內聯樣式標籤以及各個 HTML 元素的樣式屬性。它還支援大多數表現性 HTML 屬性。

    這是一個 PHP 的工具,有幾點注意:

    1. 如果需要連外部圖片的話需要開啟設定,關鍵字請找:isRemoteEnabled
    2. 圖片或是連結請用絕對路徑。
    3. 不是全支援 CSS 3
    4. 通常會指定紙張樣式,這塊 html 需要考慮平面印刷的特色才行。

    接下來讓 AI 說明,使用 dompdf 支援可使用中文字型的方法。


    要在 Dompdf 中正確顯示中文,您需要引入支援中文的字體。以下是詳細步驟:

    1. 安裝 Dompdf:如果尚未安裝,請使用 Composer 安裝 Dompdf:
       composer require dompdf/dompdf
    1. 下載 load_font.php 工具:從 Dompdf 的 utils 儲存庫下載 load_font.php,並將其放置在 vendor/dompdf/dompdf 目錄下,與 libsrc 目錄同級。
    2. 下載中文字體:取得支援中文的字體檔案(如 simsun.ttfmsyh.ttf),並將其放置在與 load_font.php 相同的目錄中。
    3. 修改 load_font.php:確保 load_font.php 正確載入自動加載器。
       // 確認以下路徑正確
       require_once "../../autoload.php";
    1. 安裝字體:在命令列中執行以下命令來安裝字體:
       php load_font.php 字體名稱 字體檔案.ttf

    例如,若字體名稱為 simsun,字體檔案為 simsun.ttf,則執行:

       php load_font.php simsun simsun.ttf
    1. 確認字體安裝成功:在 vendor/dompdf/dompdf/lib/fonts 目錄中,應該能看到新生成的字體檔案(如 simsun.ttfsimsun.ufm)。此外,檢查 installed-fonts.json 檔案,確認字體資訊已被記錄。
    2. 在 CSS 中引用字體:在您的 HTML 或 CSS 中,使用 @font-face 規則引用新安裝的字體,並在需要的地方設置 font-family
       @font-face {
           font-family: 'simsun';
           src: url('path/to/simsun.ttf') format('truetype');
       }
       body {
           font-family: 'simsun';
       }

    請確保 src 的路徑正確指向字體檔案的位置。

    1. 生成 PDF:在生成 PDF 的程式碼中,確保載入的 HTML 包含上述字體設定。以下是範例程式碼:
       use Dompdf\Dompdf;
       use Dompdf\Options;
    
       // 初始化 Dompdf
       $options = new Options();
       $options->set('isRemoteEnabled', true);
       $dompdf = new Dompdf($options);
    
       // 載入 HTML 內容
       $html = '<html><head><style>
       @font-face {
           font-family: "simsun";
           src: url("path/to/simsun.ttf") format("truetype");
       }
       body {
           font-family: "simsun";
       }
       </style></head><body>您的中文內容</body></html>';
       $dompdf->loadHtml($html);
    
       // 設定紙張大小和方向
       $dompdf->setPaper('A4', 'portrait');
    
       // 生成 PDF
       $dompdf->render();
    
       // 輸出 PDF
       $dompdf->stream('document.pdf');

    請確保 @font-face 中的 src 路徑在 HTML 中是可訪問的。

    按照上述步驟,您應該能夠在 Dompdf 中成功引入並使用中文字體,確保生成的 PDF 正確顯示中文內容。


    我在 Github 上弄了兩個頁面可以把他架設起來試試看,請點這裡

    同場加映,有時我們想找中文開源字型,請到這裡

    可以 filiter 你要的字型,點擊搜尋出來的字型後再點擊 「Get font」按鈕。

    在這裡可以從 Download all 中下載字型,也可以從 embed code 中找到字型的連結。

    舉例像是抓出來的這個:

    https://fonts.googleapis.com/css2?family=Noto+Sans+TC:[email protected]&family=Noto+Serif+TC:[email protected]&display=swap

    打開來會得到一串 @font-face 的 css 資料,除了可以引用以外,也可以從裡面複製處來使用。 以上!

  • 使用 NoteGPT 生成「京華城土地違法容積獎勵案」起訴書摘要

    使用 NoteGPT 生成「京華城土地違法容積獎勵案」起訴書摘要

    算是記錄一下歷史,先附上這件事情相關新聞連結,新聞是隨便抓的,最近被小白癡噴「假中立」這件事,提醒我最後要記得抱怨一下。

    而之所要製作摘要的起因,是因為在 2024-12-26 檢方偵結起訴,並且公布了一份起訴書,內文字非常多。政治人物又接近於偶像的角色會有非常多正反兩方立場,甚至是極端的聲音,我看到網路上有人酸館長看起訴書非常快這件事(原文之一,請參考),從健身房回來以後突然想到:「他一定是用 AI 摘要!」

    事實與否不重要,於是我嘗試將起訴書內容做成摘要看看,是不是和館長的觀點會相近?以下記錄操作步驟:

    首先我必須找原文,找到了 pdf 檔案(這裡),但把檔案直接丟進去的話 NoteGPT 會顯示抓不出文字,於是我嘗試找看有沒有文字檔。

    結果發現鏡新聞竟然有發完整原文的一篇新聞(這裡),不愧人稱鏡檢,他們真的很討厭柯文哲我猜。

    看得到文字之後,我用 js 把底下內文抓出來,先儲存成一個 txt 檔案(這裡),這份 txt 是直接採文字內容,所以分行什麼的都沒有,給電腦看的沒關係。

    將檔案丟進去 Google 的 NoteGPT 裡面,這裡做過幾次嘗試,先是如果單純以文字貼上的形式,字數會太多無法使用;如果是用雲端公開連結的話,會顯示抓不到資料,用 docx 檔案也會顯示抓不到的問題,我想應該是擷取的功能有些限制,最後純文字上傳,耗費 19 點得以產生摘要。

    有趣的是探索 NoteGPT 生整摘要的過程。先附上筆記截圖,有簡體字不喜的話可以先去睡:

    生成了三份內容,第一份是原始摘要總結,包含了 Summary, Highlights, Outline, Keywords. 第二份是樹狀圖,第三份是使用「法律文件總結助手」來生成,NoteGPT 有很多不同的角色提示詞,也可以自訂想要的提示詞,我資質駑鈍,所以先只用了這三個現成的產生。

    而 NoteGPT 也會有匯出和分享功能,匯出結果在這裡,分享連結請點這裡(需登入)。要注意如果是用匯出 pdf ,請記得先把背景調整成淺色系,如果是深色的話,匯出的字會是白色的,但 pdf 背景也是白色的就看不清楚,這應該算是 bug,笑死。

    我將使用過的所有資料和備份、截圖等都放在這裡:

    不知道這和館長看到的內容有沒有很像?我沒讀完全文,不敢發表評論。還是提醒一下 AI 摘要與重點可能會有各種狀況產生錯誤與誤解的地方,和新聞媒體不同的地方是,新聞亂報有人負責,有法可據,如果你把 AI 生成的東西當作你的東西,你就要承受 AI 出錯的代價,如果明知如此卻又故意隱瞞,就有欺騙的嫌疑了,請三思。

    最後認真想評論一下關於「假中立」的這種評價,都 2025 年了,還有人在講。 我認真思考了兩天,我想這應該是因為角色錯誤期待造成的問題,例如把單口喜劇/站立喜劇的表演當作是脫口秀,甚至研討會議題來看,或是把一般人發表的內容用新聞的標準來看。認真說,我覺得這是低級錯誤,我必須得要引以為戒,要覺查到自己有期待錯誤的問題才行。

    當然情緒上沒有那麼 peace,剛在健身房做 facepull 到一半就突然想到:以後看到誰在那邊說 「xxx 假中立」我就回「沒錯~你最中立」按讚分享追蹤,盯著他,爬蟲抓他發文。他媽的但凡他發表任何一個觀點就把他的中立立場抓出來鞭。

    想想就刺激,馬上再多做一組。

  • Sublime Text3 檢查 Codeigniter4 專案的外掛

    Sublime Text3 檢查 Codeigniter4 專案的外掛

    使用 Sublime Text 檢查 CodeIgniter 4 專案的命名規範與 use 語句。

    在 CodeIgniter 4 開發中,為了提升專案的可維護性,遵守檔案命名規範與 use 語句的正確性是非常重要的。然而,手動檢查這些細節可能耗時且容易出錯。為了解決這個問題,我開發了一款 Sublime Text 外掛,專門用於自動檢查 CodeIgniter 4 專案的命名規範和 use 語句。

    在這篇文章中,我將介紹這個外掛的功能、使用方式、注意事項,以及如何對其進行客製化修改。


    外掛功能(截至 2024-12-13)

    這個外掛的主要功能是檢查 PHP 檔案是否符合 CodeIgniter 4 的命名規範和 use 語句的使用規則:

    1. 檔案命名規範檢查
      • 確保所有 PHP 檔案名稱遵循 PascalCase 並以 .php 結尾。
      • 舉例:MyClass.php 是正確的命名,my_class.php 則會觸發警告。
    2. use 語句檢查
      • 檢查是否所有使用到的類別名稱都已經通過 use 正確引入。
      • 找出未被使用的類別,協助開發者清理多餘的 use 語句。
    3. CodeIgniter 4 專案結構檢查
      • 自動檢測專案是否為 CodeIgniter 4,要求至少包含以下目錄:
        • 必須有:app/writable/
        • 至少存在:public/vendor/

    如何安裝與使用

    1. 下載外掛
    2. 安裝外掛
      • 將外掛放入 Sublime Text 的 Packages 目錄中: Sublime Text > Preferences > Browse Packages 將外掛資料夾解壓縮到上述目錄內。
    3. 保存 PHP 檔案以觸發檢查
      • 在 Sublime Text 中打開 CodeIgniter 4 專案的 PHP 檔案,進行編輯後保存。
      • 外掛會自動檢查檔案並在 Sublime Text 狀態列中顯示結果。
      • 如果發現錯誤,會彈出對話框提醒,顯示具體問題。

    使用注意事項(截至 2024-12-13)

    1. 適用專案
      • 此外掛僅適用於 CodeIgniter 4 專案,需保證專案根目錄存在 .env 檔案,並符合 CodeIgniter 4 的基本目錄結構。
    2. 支援的檔案類型
      • 僅檢查 .php 檔案,其他檔案類型將被忽略。
    3. 檢查邏輯
      • 外掛會移除 PHP 中的註解與引號內容來確保檢查不受干擾,但可能會忽略某些極端情況。例如,代碼中以字串拼接的動態類別名稱。

    如何進行修改

    如果你需要針對專案需求進一步客製化這個外掛,可以參考以下指引:

    1. 修改專案結構檢查邏輯

    • is_codeigniter4_project 方法中,你可以自訂需要檢查的目錄結構: def is_codeigniter4_project(self, directory): required_paths = ["app", "writable"] optional_paths = ["public", "vendor"] for path in required_paths: if not os.path.isdir(os.path.join(directory, path)): return False if not any(os.path.isdir(os.path.join(directory, path)) for path in optional_paths): return False return True

    2. 新增自訂檢查規則

    • 如果需要檢查額外的命名規範或程式碼規範,可以在 check_file_namingcheck_use_statements 方法中新增對應邏輯。

    3. 排除特定情境

    • 若某些專案使用特定的非標準命名方式,可以修改正則表達式來放寬檢查。例如: if not re.match(r"^[A-Z][a-zA-Z0-9_]*\.php$", base_name):

    4. 偵錯模式

    • 在開發或調試外掛時,可以透過 print 將日誌輸出到 Sublime Text 的 Console(`Ctrl+“)。

    結語

    這個 Sublime Text 外掛旨在提升 CodeIgniter 4 專案的開發效率,減少手動檢查的時間成本。如果你有其他需求或遇到問題,歡迎前往 GitHub 儲存庫 提交 Issue 或 Pull Request。

    希望這款工具能夠成為你在 CodeIgniter 4 開發中的得力助手!

    笑死,現在部落格用 AI 幫忙生成,講的比自己清楚。附上連結:

  • Debian 11 中更改系統語言,解決亂碼問題

    Debian 11 中更改系統語言,解決亂碼問題

    我最近有點想試試看用 AI 寫部落格,絕對不是因為我懶。

    如果你在使用 Debian 11 時,發現終端機中跳出一堆莫名其妙的菱形方塊亂碼,那不用擔心,這是語系設定的問題!我需要把語系改回英文。

    以下步驟說明:


    Step 1:修改語言設定檔
    首先,我們需要調整系統的語言設定。打開終端機,輸入以下指令來編輯設定檔案:

    sudo nano /etc/default/locale

    進入檔案後,會看到類似這樣的內容:

    LANG="zh_CN.UTF-8"
    LANGUAGE="zh_CN:zh"

    把它改成下面的樣子:

    LANG="en_US.UTF-8"
    LANGUAGE="zh_CN:zh:en_US:en"

    這樣的設定表示系統的主要語言改為英文。


    Step 2:重啟系統
    完成上面步驟後,重新啟動系統,讓設定生效:

    sudo reboot

    以上,修改了一些資訊表達不是我想要的內容,AI 文字有夠假掰。

  • 解決 PHP8.2  mb_convert_encoding 方法已經棄用的問題。

    解決 PHP8.2 mb_convert_encoding 方法已經棄用的問題。

    PHP 中 mb_convert_encoding() 實作了將字串從一種字元編碼轉換為另一種字元編碼,但是在 PHP 8.2 時這個方法就棄用了,找到解決辦法並且測試一下。

    先講結論,應該使用這個方法

    function _($string)
    {
        return mb_encode_numericentity(
            htmlspecialchars_decode(
                htmlentities($string, ENT_NOQUOTES, 'UTF-8', false)
                , ENT_NOQUOTES
            ), [0x80, 0x10FFFF, 0, ~0],
            'UTF-8'
        );
    }

    參考這裡是正確答案:

    測試程式碼:

    <?php
    
    $string = '中文:!"$%&/()=ÖÄÜöäü<<accentué За матеріалами';
    
    
    echo mb_convert_encoding($string, 'HTML-ENTITIES', 'utf-8')."\n\n";
    // 方法 1
    echo mb_encode_numericentity(
        htmlspecialchars_decode(
            htmlentities($string, ENT_NOQUOTES, 'UTF-8', false)
            ,ENT_NOQUOTES
        ), [0x80, 0x10FFFF, 0, ~0],
        'UTF-8'
    );
    echo "\n\n";
    // 方法 2
    echo htmlspecialchars_decode(htmlentities($string));

    變化後方法 1 和原方法是一樣的。先自首,我其實看不太懂這意思,丟個 AI 解釋水字數一下:

    這段程式碼通過以下步驟將 UTF-8 字符串轉換為 HTML 實體:

    1. htmlentities():將特殊字符轉換為 HTML 實體,但不處理引號。
    2. htmlspecialchars_decode():將 HTML 實體轉回原始字符。
    3. mb_encode_numericentity():將範圍內的字符轉換為數值實體表示,這裡的範圍 [0x80, 0x10FFFF] 適用於大多數 Unicode 字符。

    此方法提供更精確的 HTML 實體處理,尤其適合多字節字符編碼。

    接下來就是接 DOMDocument 做 HTML 解析了,DOMDocument 還會有一個問題是 HTML5 不太支援,這算是用 PHP 做爬蟲的原罪吧。