🏠️Top Page

🖊️おもしろき こともなき世をおもしろく 住みなすものは 心なりけり.

⏩️映画、Fukushima 50(フクシマ フィフティ)を観ました.

おはようございます.映画、Fukushima 50(フクシマ フィフティ)をネトフリで再度観ました.いろいろと考えさせられる内容だった.これを見ると南海トラフ巨大地震が発生したときに愛媛県にある伊方原発は大丈夫なのかという事が脳裏に過ぎりました.調べてみると伊方原発は津波10メートルまで耐えれるということらしい、もし仮に南海トラフ巨大地震が発生したとしても伊方原発の方には4.5メートルの津波しか来ないとの事.

なので福島の原発事故(災害)のような事は発生しないという事らしいのだけども、福島の原発も10メートルを超える津波は来ないという想定でしたが、東日本大震災時には10メートルを超える津波が押し寄せてきたわけです.

想定外のことが起こるかもという事を考えて設計していない、これが事なかれ主義な国のすることだなと...今では原発反対という人も減ってきているけれども映画フクシマフィフティを観ると島国の日本で原発を稼働させるのはリスクの方が大きいと思います.

これから将来の起こることを考えるとクリーンな発電所を増やしていくべきなのではないのかと・・・.

本当に映画は事実に基づく映画なので、ただただ大変な思いをした現場の方々には何も言えないですよ.後手後手の東電の対応や政治家などに不信感を抱いた自分がいました.実際は、それぞれ懸命に頑張っていたと思いますが、、、、.これが日本という国なのかも知れないですね.

明日へ続く

⏩️ワードプレスのテーブルwp_postsデータを取ってきてLaravelで表示.

おはようございます.ワードプレスのテーブル(wp_posts)データを取ってきて別サイト(Laravel)にて表示してます.別サイトには広告が付かない感じです.因みにデータは自サイトのブログデータを使用していますが随時去年あたりのデータから取得するようにSQLに記述しています.

尚、どうやって取得しているかをお話するとSQLのコネクション変更する設定をコンフィグフォルダのデータベースファイルに記述してモデルにもその事を明記しています.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;


class Blog extends Model
{
    protected $connection = 'second_db';
    protected $table = 'wp_posts';
}

そしてそれらを呼び出しているだけです、とても簡単なコードで動いています.そんな感じなのでブレイドのコードをシェアします、流石にコントローラーは見せられないけどYoutubeのリンクやXのリンクは出力する前に置き換えていることをヒントとしてお伝えしときますね.

<!doctype html>
<html lang="ja" class="transition-colors duration-300">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
    <meta name="robots" content="noindex,nofollow" />
    <title>blog - [taoka toshiaki]</title>
    <link rel="icon" href="https://taoka-toshiaki.com/images/g4DV7mRe_400x400.jpg?t=1752317617"
        sizes="16x16 24x24 32x32 48x48 64x64">
    <!-- Prism CSS -->
    <link id="prism-theme" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/line-numbers/prism-line-numbers.css" />
    <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.css"
        rel="stylesheet" />
    <style>
        body {
            background-color: #f9fafb;
            color: #1f2937;
            transition: background-color 0.3s, color 0.3s;
            word-wrap: break-word;
            overflow-wrap: break-word;
        }

        .dark body {
            background-color: #242425;
            color: #f9fafb;
        }

        article {
            background-color: #fff;
            transition: background-color 0.3s;
            word-wrap: break-word;
            overflow-wrap: break-word;
        }

        .dark article {
            background-color: #3d3d47;
        }

        time {
            color: #6b7280;
        }

        .dark time {
            color: #9ca3af;
        }

        .prose {
            color: inherit;
            word-wrap: break-word;
            overflow-wrap: break-word;
        }

        pre[class*="language-"] {
            overflow-x: auto;
            padding: 1em;
            border-radius: 0.5rem;
        }

        code[class*="language-"] {
            white-space: pre;
        }

        a,
        a:hover {
            border-bottom: solid 2px #fbf81c;
        }
    </style>
    @include('header_script')
</head>

<body class="transition-colors duration-300">

    <div class="max-w-3xl mx-auto p-6">
        <h1 class="text-2xl font-bold mb-6"><a href="/" class="text-current">🏠️Top Page</a></h1>
        <p class="mb-3 font-bold"><a href="/blog">🖊️</a>おもしろき こともなき世をおもしろく 住みなすものは 心なりけり.</p>
        @if (request()->input('page') == 108)
            <a href="/blog" class="text-[54px]">📖</a>
            <h1 class="text-2xl font-bold text-[108px] mb-6">108🧘️</h1>
        @endif

        <button id="darkModeToggle"
            class="mb-6 px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded">
            ダークモード切り替え
        </button>

        <div class="space-y-10">
            @foreach ($items as $item)
                <article class="shadow-md rounded-lg p-6 transition-colors duration-300">
                    <h2 class="text-xl font-semibold mb-2 break-words">⏩️{{ $item->post_title }}</h2>
                    <time class="text-sm block mb-4">{{ $item->post_date }}</time>
                    <div class="prose prose-sm max-w-none break-words">
                        {!! $item->post_content !!}
                    </div>
                </article>
            @endforeach
        </div>

        <div class="mt-10">
            {{ $items->links() }}
        </div>
    </div>
    <!-- トップに戻るボタン -->
    <button id="scrollTopBtn"
        class="fixed bottom-6 right-6 hidden bg-gray-600 text-white px-4 py-2 rounded-full shadow-lg hover:bg-gray-700 transition-opacity">
        ▲ 上へ戻る
    </button>
    <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
    <script src="https://cdn.jsdelivr.net/clipboard.js/1.5.13/clipboard.min.js"></script>
    <!-- Prism.jsのコアファイル -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
    <!-- Prism.jsのオートローダ -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
    <!-- Toolbarプラグインのスクリプト -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.js"></script>
    <!-- その他のプラグインのスクリプト -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/highlight-keywords/prism-highlight-keywords.min.js"></script>

    <script>
        const toggleBtn = document.getElementById('darkModeToggle');
        const prismTheme = document.getElementById('prism-theme');
        const darkThemeHref = 'https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-tomorrow.css';
        const lightThemeHref = 'https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.css';

        if (localStorage.getItem('darkMode') === 'true') {
            document.documentElement.classList.add('dark');
            prismTheme.href = darkThemeHref;
        }

        toggleBtn.addEventListener('click', () => {
            const isDark = document.documentElement.classList.toggle('dark');
            prismTheme.href = isDark ? darkThemeHref : lightThemeHref;
            localStorage.setItem('darkMode', isDark);
        });

        document.addEventListener("DOMContentLoaded", () => {
            document.querySelectorAll('pre[class*="lang-"]').forEach(pre => {
                const match = pre.className.match(/lang-(\w+)/);
                if (match) {
                    const lang = match[1];
                    pre.className = `language-${lang} line-numbers`;
                    const code = pre.querySelector('code');
                    if (code) code.className = `language-${lang}`;
                }
            });
            // トップへ戻るボタンの処理
            const scrollTopBtn = document.getElementById("scrollTopBtn");
            window.addEventListener("scroll", () => {
                scrollTopBtn.classList.toggle("hidden", window.scrollY < 200);
            });

            scrollTopBtn.addEventListener("click", () => {
                window.scrollTo({
                    top: 0,
                    behavior: "smooth"
                });
            });
        });

        //全選択ボタンを作成&クラス名付与
        Prism.plugins.toolbar.registerButton('select-code', function(env) {
            var newButton = document.createElement('button');
            newButton.className = 'code-select-btn';
            newButton.innerHTML = 'コードを選択';

            newButton.addEventListener('click', function() {
                if (document.body.createTextRange) { // ms
                    var range = document.body.createTextRange();
                    range.moveToElementText(env.element);
                    range.select();
                } else if (window.getSelection) { // moz, opera, webkit
                    var selection = window.getSelection();
                    var range = document.createRange();
                    range.selectNodeContents(env.element);
                    selection.removeAllRanges();
                    selection.addRange(range);
                }
            });
            return newButton;
        });

        //使用言語表示ボタンを作成&クラス名付与
        Prism.plugins.toolbar.registerButton('show-lang-btn', function(env) {
            var newButton2 = document.createElement('button');
            newButton2.className = 'show-lang-btn';
            newButton2.innerHTML = env.language;
            return newButton2;
        });

        $(function() {
            //各ボタン要素の親要素にクラス名付与
            $('.toolbar-item .code-select-btn').parents('.toolbar-item').addClass('code-select');
        });
    </script>

</body>

</html>

明日へ続く

⏩️Jsonの返却時に便利ですよを貼っときますねと雑煮.

おはようございます.Jsonの返却時に便利ですよを貼っときますね、こう書くのがベストプラクティスなのか分かりませんが便利な時がありますので覚えておいて損はない書き方だと思います.

//Jsonの返却時に便利ですよ👍️
const obj = {
  name: "Taoka",
  age: 25,
  country: "Japan"
};
Object.entries(obj).forEach(([key, value]) => {
    console.log(key,value)
});
//console log ⬇️
//name Taro
//age 25
//country Japan

雑煮ではなくて雑談です、最近?のUPDATEでウィンドウズ11のメモ帳でもマークダウン記法が使えるようになったソウデス.ちょっと驚きました、なんかメモ帳ってウィルスに感染しないぐらい強固なアプリなイメージがあるので、いまのメモ帳は今まで無かったものを拡張していっている感じがしてちょっと心配なイメージが少しあります.

便利になることは良いことですが、拡張していくとバグや脆弱性が発生するので大丈夫かなって思います.マイクロソフト開発陣営は優秀な人だと思いますが、やっぱ心配.

全然関係ない話をもう一つウィンドウズをアップデートしていく内に何だか家のパソコンが熱暴走で...固まりだした.この原因を探ろうとログを見て解決したいと思っています.原因が分かったら記事にしようと思います.

明日へ続く

⏩️チャットワークのAPIを使ってみました.プロンプトでほぼ書いています.

おはようございます.チャットワークのAPIを使ってみました.プロンプトでほぼ書いたコードになります、チャットGPTの無料版にリファレンスのURLリンクとPHPのクラス化、リターンに$thisで返却出来る所は$thisを使用してスマートにコードを書いてと指示を出しました.

出来上がったコードが下記になります.ソースコードは自分の方でモンキーテスト的に動かしてみましたが、ちゃんと動作するようです.

<?php
class ChatworkClient
{
    private string $apiToken;
    private string $baseUrl = 'https://api.chatwork.com/v2';
    private int $retryCount = 3;
    private int $retryDelay = 1000000; // microseconds

    public function __construct(string $apiToken)
    {
        $this->apiToken = $apiToken;
    }

    public function setRetry(int $count, int $delayMicroseconds): self
    {
        $this->retryCount = $count;
        $this->retryDelay = $delayMicroseconds;
        return $this;
    }

    private function request(string $method, string $path, array $params = []): array
    {
        $attempts = 0;

        while ($attempts < $this->retryCount) {
            $attempts++;

            $ch = curl_init();
            $url = $this->baseUrl . $path;

            if ($method === 'GET' && $params) {
                $url .= '?' . http_build_query($params);
            }

            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            $headers = ['X-ChatWorkToken: ' . $this->apiToken];

            if (in_array($method, ['POST', 'PUT', 'DELETE'])) {
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
                $headers[] = 'Content-Type: application/x-www-form-urlencoded';
            }

            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

            $body = curl_exec($ch);
            $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($error) {
                if ($attempts < $this->retryCount) {
                    usleep($this->retryDelay);
                    continue;
                }
                throw new RuntimeException("cURL error after {$attempts} attempts: {$error}");
            }

            if ($status >= 200 && $status < 300) {
                return [
                    'status' => $status,
                    'body' => $body ? json_decode($body, true) : null,
                ];
            }

            if ($attempts < $this->retryCount && $status >= 500) {
                usleep($this->retryDelay);
                continue;
            }

            return [
                'status' => $status,
                'body' => $body ? json_decode($body, true) : null,
            ];
        }

        throw new RuntimeException("Request failed after {$this->retryCount} attempts");
    }

    public function setToken(string $token): self
    {
        $this->apiToken = $token;
        return $this;
    }

    public function me(): array
    {
        return $this->request('GET', '/me');
    }
    public function getMyStatus(): array
    {
        return $this->request('GET', '/my/status');
    }
    public function getMyTasks(array $filters = []): array
    {
        return $this->request('GET', '/my/tasks', $filters);
    }
    public function getContacts(): array
    {
        return $this->request('GET', '/contacts');
    }
    public function getRooms(): array
    {
        return $this->request('GET', '/rooms');
    }
    public function createRoom(array $params): array
    {
        return $this->request('POST', '/rooms', $params);
    }
    public function getRoom(int $roomId): array
    {
        return $this->request('GET', "/rooms/{$roomId}");
    }
    public function updateRoom(int $roomId, array $params): array
    {
        return $this->request('PUT', "/rooms/{$roomId}", $params);
    }
    public function deleteRoom(int $roomId, string $action = 'leave'): array
    {
        return $this->request('DELETE', "/rooms/{$roomId}", ['action_type' => $action]);
    }

    public function getMembers(int $roomId): array
    {
        return $this->request('GET', "/rooms/{$roomId}/members");
    }
    public function updateMembers(int $roomId, array $params): array
    {
        return $this->request('PUT', "/rooms/{$roomId}/members", $params);
    }

    public function getMessages(int $roomId, bool $force = false): array
    {
        return $this->request('GET', "/rooms/{$roomId}/messages", ['force' => $force ? 1 : 0]);
    }

    public function postMessage(int $roomId, string $body, bool $selfUnread = false): self
    {
        $this->request('POST', "/rooms/{$roomId}/messages", ['body' => $body, 'self_unread' => $selfUnread ? 1 : 0]);
        return $this;
    }

    public function markRead(int $roomId): self
    {
        $this->request('PUT', "/rooms/{$roomId}/messages/read");
        return $this;
    }

    public function markUnread(int $roomId): self
    {
        $this->request('PUT', "/rooms/{$roomId}/messages/unread");
        return $this;
    }

    public function getMessage(int $roomId, int $messageId): array
    {
        return $this->request('GET', "/rooms/{$roomId}/messages/{$messageId}");
    }

    public function getRoomTasks(int $roomId, array $filters = []): array
    {
        return $this->request('GET', "/rooms/{$roomId}/tasks", $filters);
    }

    public function createTask(int $roomId, array $params): array
    {
        return $this->request('POST', "/rooms/{$roomId}/tasks", $params);
    }

    public function uploadFile(int $roomId, string $filePath, string $message = ''): array
    {
        if (!file_exists($filePath)) {
            throw new InvalidArgumentException("File not found: {$filePath}");
        }

        $ch = curl_init();
        $url = $this->baseUrl . "/rooms/{$roomId}/files";
        $cfile = curl_file_create($filePath);

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-ChatWorkToken: ' . $this->apiToken]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $cfile, 'message' => $message]);

        $body = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if (curl_errno($ch)) {
            throw new RuntimeException(curl_error($ch));
        }

        curl_close($ch);
        return ['status' => $status, 'body' => json_decode($body, true)];
    }
}

人が今回のコードを書いた場合、早い人でも10分ぐらいはコードを書かないといけないと思います、どんなに早くてもそれぐらいの時間は必要だと思いますが、生成AIはこれを数十秒で書ける訳ですから、確実に時間短縮になります.

なので人工知能が使える現場は間違いなく最初のコード出力は人工知能に任せた方が良いです.特に新規案件の土台は生成AIに任せると開発コストは削減出来ます.

明日へ続く

⏩️映画、スーパーマンを観てきました.エンドクレジットにおまけ有り

おはようございます.映画、スーパーマンを観てきました.エンドクレジットにおまけ有りのスーパーマンを観てきました、これ大人が観て楽しめるかという回答で言うとまぁまぁ楽しめるかなと思います.

ストーリー展開は良きアメリカ映画のストーリー展開だと思ってください、なので安心して見えます.でも何ていうか今の時代を上手く写しているようにも思えました.いまアメリカが置かれている政治的な要素がこの映画を通してみて取れました.

もう一つ思ったことが、ゴジラマイナス・ワンがいかに優秀なんだと言うことが分かります.ゴジラマイナス・ワンのVFXを手掛けた白組は35人しかいない中、ハリウッドと同等の映像表現を手掛けた訳です、それに対してスーパーマンのエンドクレジットを観ているとVFXなどに関わった関係者が100人を越していたと思います.

白組優秀だわって思いますよね👏.

因みにエンドクレジットには2回おまけ映像が流れます.

まとめ、まぁまずまずの映画でした.

明日へ続く

⏩️laravelはenvで設定するのがベターですけど、そうではない環境もenvで

おはようございます.laravelはenvで設定するのがベターですけど、そうではない環境もenvで構築した方が良いです、なぜかと言えばテスト環境との切り替えが簡単になるということなんです.

使い方はこんな感じまずComposerのライブラリをインストールします.

composer require vlucas/phpdotenv

次に使用方法はこんな感じです.こうしとけば結構楽になりますし使いまわしの時に便利です、Laravel(ララベル)ってライブラリの纏まりで構築されているのでワードプレスの環境でも組み込む事は可能です.自分が使用しているのはenv周りとデータベース周りのライブラリです.

require_once __DIR__ . '/vendor/autoload.php';

use Dotenv\Dotenv;

// .env ファイルを読み込む
$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();

// 環境変数の取得
echo getenv('APP_NAME');     // ✅ OK
echo $_ENV['APP_NAME'];      // ✅ OK
echo env('APP_NAME');        // ❌ Laravel外では未定義

そうそう.envをルート上に置いている場合は.htaccessに下記の記述を書くことをお忘れなく!!これを置いていない場合は筒抜けになります(エンジンエックスの場合も記載しときますね).

<Files .env>
 require all denied
</Files>
location ~ /\.env {
    deny all;
}

明日へ続く

⏩️YouTubeに力を入れていこうと思っているけど夢ですね.

おはようございます.YouTubeに力を入れていこうと思っているけど夢ですね.登録者数が5000人で15万円も夢ではないそうです.5000人っていうのは底辺YOUTUBERと言われるランクなのですが、それでも全体の13%の割合だそう.

今ではチャンネルの売り買いもされているそうなので、お金を出せばチャンネルを買うことが出来るそうなのでいきなり登録者数1万人から始めることも出来ます.たまに芸能人でもないのに数本の投稿で1万人ってのはお金の力が働いている気がします.

因みに自分のチャンネル数は45人です、ここから収益が得られる500人まで頑張ってYOUTUBE投稿を行っていこうと思っているけど何せネタが無いネタが無い.YOUTUBEでは成功しているひとの人前するのが一番良いらしいですね.

なので、今までダラダラ見ていたYOUTUBEをちょっと見方を変えて研究していこうと思います.上手く行ってない人と成功している人の違いなどを学習しつつ週一UPで行っていこうと意気込んでいます.

明日へ続く

⏩️歯医者へ行ってきました.事後報告.

おはようございます.歯医者へ行ってきました.特に虫歯になったという訳では無いだけども定期的に歯医者へ行きます.感覚的には2、3年に一回は行っていたのだけども前回行ってから数年は確実に経過している気がします.

なぜ定期的に歯医者に行くようになったかというと歯は大事だという事に気づいたので、行くようになった感じですね、歯は身体に確実に影響を与えますし影響を受けます.本当に歯は大事だということ.

トイウワケデ、いつも行っている歯医者さんに行ってきた訳ですが、虫歯はなかったですが知覚過敏がありました、なのでその治療と歯石を取ったら終わりだそう.あと2回ぐらい通えば終わりになるじゃないかと思います.

明日へ続く

⏩️暑いので大阪・関西万博やっぱり辞めようかなという思いがよぎる.

おはようございます.暑いので大阪・関西万博やっぱり辞めようかなという思いがよぎる.もし行くとなるともうそろそろ予約しか無いと駄目な感じなのですが未だに悩んでいます.

理由はYOUTUBEで大阪・関西万博内がどんなになっているのかという事を一通り観たので暑い思いまでして見に行くのは辛いかもと思いはじめたという理由があります、あと金銭的な理由.

もし行くなると平日の何処かで行くつもりでいます、そして泊まらずに帰ってきます、要するに日帰りですね.

もし行くとなると9月ぐらいになりそうですが9月も灼熱だと思います.暑いのは嫌いではないですが、帰りの飛行機で汗だくになっているのは避けたい気がします.まぁ着替えを持っていけば良い話ですがどうなんだろう.

多分、一生に一回ぐらいしか体験することが出来ないイベントなので見とけばよかったという後悔も残りそうなんですよね、悩ましい.

明日へ続く

⏩️格安SIMでも4Gから5Gに切り替える事が無料で出来るみたい.

おはようございます.格安SIMでも4Gから5Gに切り替える事が無料で出来るみたいだったので、早速切り替えてみました.5G帯域を使用できるようになるには、ちょっと時間が掛かりましたがこれで外で使用するときは5Gで使用出来ます.

5G帯域が役に立つのは自分の場合は当分の間無いかなと思っています、平日はリモートワークなのでwifi環境下にいるのでほぼモバイル通信費がかからないです.

そう思っていたのですが、休みの日に外で勉強する時間を設けようと今思っていてその時にディザリングすることもあるので、そういう時に使用すると結構便利なんじゃないかなって思っていて近日中に試してみたいと思います.

トイウコトで近日中にオーテピア高知図書館に出かけてみます.カーミルでも良かったのですが高知市の方はミリ波もカバーしているようなので速いかなと思っています.

明日へ続く