<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Yii2  |  takeHo（たけほ）のへなちょこ台帳</title>
	<atom:link href="https://blog.takeho.com/category/web/yii2/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.takeho.com</link>
	<description>いわゆる自由帳ってところです。</description>
	<lastBuildDate>Tue, 14 Jul 2026 05:48:07 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6</generator>

<image>
	<url>https://blog.takeho.com/wp-content/uploads/2024/08/icon-150x150.png</url>
	<title>Yii2  |  takeHo（たけほ）のへなちょこ台帳</title>
	<link>https://blog.takeho.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Yii2アプリに&#8221;会話しながらコードを書いてくれる&#8221;AIエージェントを組み込む</title>
		<link>https://blog.takeho.com/ujjf3jfa14ay1iw2kxru9dqkzv4py7jl/</link>
					<comments>https://blog.takeho.com/ujjf3jfa14ay1iw2kxru9dqkzv4py7jl/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Tue, 14 Jul 2026 10:44:00 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[Claude]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=1900</guid>

					<description><![CDATA[この記事で作るもの 管理画面に「AIアシスタント」タブを1つ追加し、そこにチャット欄を置くだけです。 単発の「コード生成」ではなく、要件を詰めながら会話でコードを育てていくのがポイントです。Claudeはmax_toke [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"><span id="toc1">この記事で作るもの</span></h3>



<p>管理画面に「AIアシスタント」タブを1つ追加し、そこにチャット欄を置くだけです。</p>



<pre class="wp-block-code"><code>&#91;あなた] UserモデルにSNS連携用のprovider, provider_idカラムを追加するマイグレーションを書いて
&#91;Claude] 以下のマイグレーションを作成しました。中間テーブルではなくusersテーブルへの
         直接追加案です。ユニーク制約は (provider, provider_id) の複合キーにしています…
```php
         class m260714_000000_add_sns_columns_to_users extends Migration { ... }
```
         この設計だと1ユーザーが複数SNS連携する場合に対応できません。もし複数連携を
         想定しているなら中間テーブル案も出せますが、どちらにしますか？
&#91;あなた] 複数連携できるようにして
&#91;Claude] では user_social_accounts テーブルを新設する案に切り替えます…</code></pre>



<p>単発の「コード生成」ではなく、<strong>要件を詰めながら会話でコードを育てていく</strong>のがポイントです。Claudeはmax_tokensの許す限り会話履歴を保持するので、前の提案を踏まえた修正依頼にも自然に対応できます。</p>



<h3 class="wp-block-heading"><span id="toc2">全体構成</span></h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>要素</th><th>役割</th></tr></thead><tbody><tr><td><code>components/ClaudeAgent.php</code></td><td>Claude APIを叩くYii2コンポーネント</td></tr><tr><td><code>controllers/AiAssistantController.php</code></td><td>チャットのAPIエンドポイント</td></tr><tr><td><code>models/AiConversation.php</code></td><td>会話履歴（セッション or DB保存）</td></tr><tr><td><code>views/ai-assistant/index.php</code></td><td>チャットUI（Bootstrap + Fetch API）</td></tr><tr><td><code>config/params.php</code></td><td>APIキーなどの設定</td></tr></tbody></table></figure>



<p>Yii2のDI/Componentの仕組みは、LaravelでいうServiceクラスをコンテナに登録するのとほぼ同じ感覚で扱えます。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2"><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><ol><li><a href="#toc1" tabindex="0">この記事で作るもの</a></li><li><a href="#toc2" tabindex="0">全体構成</a></li></ol></li><li><a href="#toc3" tabindex="0">1. APIキーの設定</a></li><li><a href="#toc4" tabindex="0">2. Claude APIを叩くコンポーネント</a></li><li><a href="#toc5" tabindex="0">3. 会話履歴を持つコントローラー</a></li><li><a href="#toc6" tabindex="0">4. チャットUI（View）</a></li><li><a href="#toc7" tabindex="0">5. 動作イメージ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc3">1. APIキーの設定</span></h2>



<p><code>config/params.php</code> に追記します（<code>.env</code> を使っている場合はそちら経由で読み込んでください）。</p>



<pre class="wp-block-code"><code><strong>&lt;?php</strong>
return &#91;
    'claudeApiKey' =&gt; getenv('ANTHROPIC_API_KEY'),
    'claudeModel'  =&gt; 'claude-sonnet-5', // コーディング用途はSonnetでバランス良好
];</code></pre>



<p><code>web.php</code> の <code>components</code> にも登録しておくとコントローラーから <code>Yii::$app-&gt;claudeAgent</code> で呼べて便利です。</p>



<pre class="wp-block-code"><code>'components' =&gt; &#91;
    // ...既存のコンポーネント
    'claudeAgent' =&gt; &#91;
        'class' =&gt; 'app\components\ClaudeAgent',
        'apiKey' =&gt; $params&#91;'claudeApiKey'],
        'model'  =&gt; $params&#91;'claudeModel'],
    ],
],</code></pre>



<h2 class="wp-block-heading"><span id="toc4">2. Claude APIを叩くコンポーネント</span></h2>



<p>Yii2は標準で <code>yii\httpclient\Client</code>（<code>yiisoft/yii2-httpclient</code>）が使えるので、Guzzleを別途入れなくてもOKです。未導入なら <code>composer require yiisoft/yii2-httpclient</code> を実行してください。</p>



<pre class="wp-block-code"><code><strong>&lt;?php</strong>
// components/ClaudeAgent.php

namespace app\components;

use yii\base\Component;
use yii\httpclient\Client;
use yii\base\Exception;

class ClaudeAgent extends Component
{
    public string $apiKey;
    public string $model = 'claude-sonnet-5';
    public int $maxTokens = 2048;

    private const API_URL = 'https://api.anthropic.com/v1/messages';
    private const API_VERSION = '2023-06-01';

    /**
     * @param array $history &#91;&#91;'role' =&gt; 'user'|'assistant', 'content' =&gt; string], ...]
     * @param string $systemPrompt Yii2固有の文脈を教えるシステムプロンプト
     * @return string アシスタントの返答テキスト
     */
    public function chat(array $history, string $systemPrompt): string
    {
        $client = new Client(&#91;'baseUrl' =&gt; '']);

        $response = $client-&gt;createRequest()
            -&gt;setMethod('POST')
            -&gt;setUrl(self::API_URL)
            -&gt;setHeaders(&#91;
                'x-api-key' =&gt; $this-&gt;apiKey,
                'anthropic-version' =&gt; self::API_VERSION,
                'content-type' =&gt; 'application/json',
            ])
            -&gt;setContent(json_encode(&#91;
                'model' =&gt; $this-&gt;model,
                'max_tokens' =&gt; $this-&gt;maxTokens,
                'system' =&gt; $systemPrompt,
                'messages' =&gt; $history,
            ]))
            -&gt;send();

        if (!$response-&gt;isOk) {
            throw new Exception('Claude API error: ' . $response-&gt;content);
        }

        $data = $response-&gt;data;
        // content配列からtext種別を連結（tool_use等が混じる場合を考慮）
        $text = '';
        foreach ($data&#91;'content'] as $block) {
            if ($block&#91;'type'] === 'text') {
                $text .= $block&#91;'text'];
            }
        }
        return $text;
    }
}</code></pre>



<p><strong>ポイント</strong></p>



<ul class="wp-block-list">
<li><code>system</code> パラメータにYii2固有のルール（後述）を書くことで、的外れなLaravel流の回答を防ぎます。</li>



<li><code>content</code> を配列でループしているのは、将来ツール実行（tool_use）を組み込む拡張余地を残すためです。</li>
</ul>



<h2 class="wp-block-heading"><span id="toc5">3. 会話履歴を持つコントローラー</span></h2>



<p>会話はDBに残すのが理想ですが、まずは最小構成としてセッション保存にします。</p>



<pre class="wp-block-code"><code><strong>&lt;?php</strong>
// controllers/AiAssistantController.php

namespace app\controllers;

use Yii;
use yii\web\Controller;
use yii\web\Response;
use yii\filters\VerbFilter;

class AiAssistantController extends Controller
{
    public function behaviors()
    {
        return &#91;
            'verbs' =&gt; &#91;
                'class' =&gt; VerbFilter::class,
                'actions' =&gt; &#91;
                    'send' =&gt; &#91;'post'],
                    'reset' =&gt; &#91;'post'],
                ],
            ],
        ];
    }

    public function actionIndex()
    {
        $history = Yii::$app-&gt;session-&gt;get('ai_chat_history', &#91;]);
        return $this-&gt;render('index', &#91;'history' =&gt; $history]);
    }

    public function actionSend()
    {
        Yii::$app-&gt;response-&gt;format = Response::FORMAT_JSON;

        $message = Yii::$app-&gt;request-&gt;post('message', '');
        if (trim($message) === '') {
            return &#91;'error' =&gt; 'メッセージが空です'];
        }

        $history = Yii::$app-&gt;session-&gt;get('ai_chat_history', &#91;]);
        $history&#91;] = &#91;'role' =&gt; 'user', 'content' =&gt; $message];

        $systemPrompt = &lt;&lt;&lt;PROMPT
        あなたはYii2フレームワークの上級エンジニアです。
        - 回答はYii2の作法（ActiveRecord, Widget, Behavior, RBAC等）に従うこと
        - Laravel的な書き方（Eloquentのスコープ記法など）を混ぜないこと
        - コードは動くものを示し、設計判断が分かれる場合は選択肢を提示して確認を取ること
        - 日本語で簡潔に回答すること
        PROMPT;

        try {
            $reply = Yii::$app-&gt;claudeAgent-&gt;chat($history, $systemPrompt);
        } catch (\Throwable $e) {
            Yii::error($e-&gt;getMessage(), 'claude-agent');
            return &#91;'error' =&gt; 'AIエージェントとの通信に失敗しました'];
        }

        $history&#91;] = &#91;'role' =&gt; 'assistant', 'content' =&gt; $reply];
        Yii::$app-&gt;session-&gt;set('ai_chat_history', $history);

        return &#91;'reply' =&gt; $reply];
    }

    public function actionReset()
    {
        Yii::$app-&gt;session-&gt;remove('ai_chat_history');
        Yii::$app-&gt;response-&gt;format = Response::FORMAT_JSON;
        return &#91;'status' =&gt; 'ok'];
    }
}</code></pre>



<p><code>system</code> プロンプトで「Yii2の作法に従う」「設計判断が割れる場合は確認を取る」と明示しているのが、単なるコード生成器と対話型エージェントを分ける最大のポイントです。</p>



<h2 class="wp-block-heading"><span id="toc6">4. チャットUI（View）</span></h2>



<p>Bootstrap 5（Yii2 basic templateに標準搭載）+ 素のFetch APIだけで組めます。Reactなどは不要です。</p>



<pre class="wp-block-code"><code><strong>&lt;?php</strong>
// views/ai-assistant/index.php
/** @var array $history */
use yii\helpers\Html;
use yii\helpers\Url;

$this-&gt;title = 'AIコーディングアシスタント';
<strong>?&gt;</strong>
&lt;div class="ai-assistant-index"&gt;
    &lt;h1&gt;<strong>&lt;?=</strong> Html::encode($this-&gt;title) <strong>?&gt;</strong>&lt;/h1&gt;

    &lt;div id="chat-log" class="border rounded p-3 mb-3" style="height: 480px; overflow-y: auto; background:#fafafa;"&gt;
        <strong>&lt;?php</strong> foreach ($history as $msg): <strong>?&gt;</strong>
            &lt;div class="mb-3 &lt;?= $msg&#91;'role'] === 'user' ? 'text-end' : '' ?&gt;"&gt;
                &lt;span class="badge &lt;?= $msg&#91;'role'] === 'user' ? 'bg-primary' : 'bg-secondary' ?&gt; mb-1"&gt;
                    <strong>&lt;?=</strong> $msg&#91;'role'] === 'user' ? 'あなた' : 'Claude' <strong>?&gt;</strong>
                &lt;/span&gt;
                &lt;pre class="bg-white border rounded p-2" style="white-space: pre-wrap;"&gt;<strong>&lt;?=</strong> Html::encode($msg&#91;'content']) <strong>?&gt;</strong>&lt;/pre&gt;
            &lt;/div&gt;
        <strong>&lt;?php</strong> endforeach; <strong>?&gt;</strong>
    &lt;/div&gt;

    &lt;form id="chat-form" class="d-flex gap-2"&gt;
        &lt;input type="text" id="chat-input" class="form-control"
               placeholder="例: UserモデルにSNS連携カラムを追加したい" autocomplete="off"&gt;
        &lt;button type="submit" class="btn btn-primary"&gt;送信&lt;/button&gt;
        &lt;button type="button" id="chat-reset" class="btn btn-outline-secondary"&gt;リセット&lt;/button&gt;
    &lt;/form&gt;
&lt;/div&gt;

<strong>&lt;?php</strong>
$sendUrl = Url::to(&#91;'ai-assistant/send']);
$resetUrl = Url::to(&#91;'ai-assistant/reset']);
$csrfParam = Yii::$app-&gt;request-&gt;csrfParam;
$csrfToken = Yii::$app-&gt;request-&gt;csrfToken;

$js = &lt;&lt;&lt;JS
const chatLog = document.getElementById('chat-log');
const form = document.getElementById('chat-form');
const input = document.getElementById('chat-input');

function appendBubble(role, text) {
    const wrap = document.createElement('div');
    wrap.className = 'mb-3' + (role === 'user' ? ' text-end' : '');
    wrap.innerHTML = `
        &lt;span class="badge \${role === 'user' ? 'bg-primary' : 'bg-secondary'} mb-1"&gt;
            \${role === 'user' ? 'あなた' : 'Claude'}
        &lt;/span&gt;
        &lt;pre class="bg-white border rounded p-2" style="white-space: pre-wrap;"&gt;&lt;/pre&gt;
    `;
    wrap.querySelector('pre').textContent = text;
    chatLog.appendChild(wrap);
    chatLog.scrollTop = chatLog.scrollHeight;
}

form.addEventListener('submit', async (e) =&gt; {
    e.preventDefault();
    const message = input.value.trim();
    if (!message) return;

    appendBubble('user', message);
    input.value = '';

    const res = await fetch('$sendUrl', {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: new URLSearchParams({ message: message, '$csrfParam': '$csrfToken' }),
    });
    const data = await res.json();
    appendBubble('assistant', data.reply || ('エラー: ' + data.error));
});

document.getElementById('chat-reset').addEventListener('click', async () =&gt; {
    await fetch('$resetUrl', {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: new URLSearchParams({ '$csrfParam': '$csrfToken' }),
    });
    chatLog.innerHTML = '';
});
JS;
$this-&gt;registerJs($js);
<strong>?&gt;</strong></code></pre>



<h2 class="wp-block-heading"><span id="toc7">5. 動作イメージ</span></h2>



<p><code>SiteController</code> のメニューか、<code>AppAsset</code> のナビバーに以下を追加すればアクセスできます。</p>



<pre class="wp-block-code"><code>&#91;'label' =&gt; 'AIアシスタント', 'url' =&gt; &#91;'/ai-assistant/index']],</code></pre>



<p>実際にブラウザで「Userモデルに論理削除を追加して」と送ると、Claudeは</p>



<ol class="wp-block-list">
<li><code>deleted_at</code> カラム追加のマイグレーション</li>



<li><code>SoftDeleteBehavior</code>（Yii2公式の <code>yii2tech/ar-softdelete</code> or 自前Behavior）の実装案</li>



<li>既存クエリへの影響（デフォルトスコープの扱い）についての確認質問</li>
</ol>



<p>という順で、コードと一緒に「次にどうしたいか」を聞き返してくる会話になります。これがChatGPT的な単発生成との一番の違いです。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/ujjf3jfa14ay1iw2kxru9dqkzv4py7jl/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DockerでYii2開発環境を最短構築！初心者でもできるMySQL・phpMyAdmin・Mailpit連携ガイド</title>
		<link>https://blog.takeho.com/build-your-yii2-development-environment-with-docker-in-no-time-a-beginners-guide-to-integrating-mysql-phpmyadmin-and-mailpit/</link>
					<comments>https://blog.takeho.com/build-your-yii2-development-environment-with-docker-in-no-time-a-beginners-guide-to-integrating-mysql-phpmyadmin-and-mailpit/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Fri, 12 Sep 2025 11:24:00 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[ウェブ・開発]]></category>
		<category><![CDATA[Composer]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Mailpit]]></category>
		<category><![CDATA[MySQL]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=1275</guid>

					<description><![CDATA[本記事では、Windows環境で Yii2（Basicテンプレート） を用いたPHPアプリ開発用に、MySQL、phpMyAdmin、そしてテスト用SMTPサーバ Mailpit（メール受信UI付き）を Docker で [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>本記事では、Windows環境で <strong>Yii2（Basicテンプレート）</strong> を用いたPHPアプリ開発用に、<strong>MySQL</strong>、<strong>phpMyAdmin</strong>、そしてテスト用SMTPサーバ <strong>Mailpit</strong>（メール受信UI付き）を <strong>Docker</strong> で一気に構築する手順を解説します。プロジェクトのルートは次のパスに固定します。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td>ルート</td><td><code>C:\Work\Workspace\Docker\example.com</code></td></tr><tr><td>フレームワーク本体</td><td><code>C:\Work\Workspace\Docker\example.com\htdocs</code></td></tr><tr><td>ドキュメントルート</td><td> <code>C:\Work\Workspace\Docker\example.com\htdocs\web</code></td></tr><tr><td>Webアクセス</td><td><a href="http://localhost:8080"> http://localhost:8080</a></td></tr><tr><td>phpMyAdmin</td><td><a href="http://localhost:8081">http://localhost:8081</a></td></tr></tbody></table></figure>



<p>この記事は <strong>「そのままコピペで動く」</strong> を重視しています。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-4"><label class="toc-title" for="toc-checkbox-4">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">事前準備とディレクトリ構成</a></li><li><a href="#toc2" tabindex="0">docker-compose.yml の作成</a></li><li><a href="#toc3" tabindex="0">PHP（php-fpm）用 Dockerfile と設定</a></li><li><a href="#toc4" tabindex="0">Nginx の設定</a></li><li><a href="#toc5" tabindex="0">php.ini の最低限の調整</a></li><li><a href="#toc6" tabindex="0">コンテナの起動と初期化</a></li><li><a href="#toc7" tabindex="0">Yii2 のインストール（コンテナ内でComposer実行）</a></li><li><a href="#toc8" tabindex="0">DB接続設定（.env と Yii2設定）</a></li><li><a href="#toc9" tabindex="0">Mailpit（メール送信テスト）設定</a></li><li><a href="#toc10" tabindex="0">動作確認（Web・DB・Mail）</a></li><li><a href="#toc11" tabindex="0">トラブルシューティング</a><ol><ol><li><a href="#toc12" tabindex="0">ポート競合</a></li><li><a href="#toc13" tabindex="0">MySQLへ接続できない</a></li><li><a href="#toc14" tabindex="0">Windows で権限由来の書き込みエラー</a></li><li><a href="#toc15" tabindex="0">ファイルの改行コード</a></li><li><a href="#toc16" tabindex="0">古いコンテナやイメージの削除でエラー</a></li><li><a href="#toc17" tabindex="0">Composerが遅い/タイムアウト</a></li></ol></li></ol></li><li><a href="#toc18" tabindex="0">よく使うコマンド集</a></li><li><a href="#toc19" tabindex="0">あとがき</a><ol><ol><ol><li><a href="#toc20" tabindex="0">引用元</a></li></ol></li></ol></li></ol></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">事前準備とディレクトリ構成</span></h2>



<p>以下のフォルダを作成します。</p>



<pre class="wp-block-code"><code>C:\Work\Workspace\Docker\example.com\
├─ htdocs\ ← Yii2のアプリ本体が入る（後で自動生成）
├─ docker\
│ ├─ php\
│ │ ├─ Dockerfile
│ │ └─ php.ini
│ └─ nginx\
│ └─ default.conf
└─ docker-compose.yml</code></pre>



<h2 class="wp-block-heading"><span id="toc2">docker-compose.yml の作成</span></h2>



<p><strong>ファイル:</strong> <code>C:\Work\Workspace\Docker\example.com\docker-compose.yml</code></p>



<pre class="wp-block-code"><code>services:
  nginx:
    image: nginx:1.27-alpine
    container_name: example_nginx
    ports:
      - "8080:80" # Web → http://localhost:8080
    volumes:
      - ./htdocs:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - php
    networks:
      - appnet

  php:
    build:
      context: ./docker/php
      dockerfile: Dockerfile
    container_name: example_php
    volumes:
      - ./htdocs:/var/www/html
    environment:
      PHP_MEMORY_LIMIT: 512M
      PHP_MAX_EXECUTION_TIME: 120
    networks:
      - appnet
  db:
    image: mysql:8.0
    container_name: example_db
    command: &#91;"mysqld", "--default-authentication-plugin=mysql_native_password", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_0900_ai_ci"]
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: example
      MYSQL_USER: app
      MYSQL_PASSWORD: apppass
      TZ: Asia/Tokyo
    ports:
      - "3307:3306" # ローカルMySQLと衝突回避したい場合は3307→3306
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - appnet

  phpmyadmin:
    image: phpmyadmin:5-apache
    container_name: example_pma
    environment:
      PMA_HOST: db
      PMA_USER: root
      PMA_PASSWORD: root
    ports:
      - "8081:80" # phpMyAdmin → http://localhost:8081
    depends_on:
      - db
    networks:
      - appnet

  mailpit:
    image: axllent/mailpit:latest
    container_name: example_mailpit
    ports:
      - "1025:1025" # SMTP (アプリからの送信先)
      - "8025:8025" # Web UI → http://localhost:8025
    networks:
      - appnet

volumes:
  dbdata:

networks:
  appnet:
    driver: bridge</code></pre>



<div class="wp-block-cocoon-blocks-tab-caption-box-1 tab-caption-box block-box not-nested-style cocoon-block-tab-caption-box"><div class="tab-caption-box-label block-box-label box-label"><span class="tab-caption-box-label-text block-box-label-text box-label-text">補足</span></div><div class="tab-caption-box-content block-box-content box-content">
<p>既存でMySQLがWindowsに入っている場合、<code>ports</code> を <code>"3307:3306"</code> のように <strong>ホスト側を3307</strong> にすると衝突しません。</p>
</div></div>



<h2 class="wp-block-heading"><span id="toc3">PHP（php-fpm）用 Dockerfile と設定</span></h2>



<p><strong>ファイル:</strong> <code>C:\Work\Workspace\Docker\example.com\docker\php\Dockerfile</code></p>



<pre class="wp-block-code"><code>FROM php:8.3-fpm-alpine

# 必要拡張の導入
RUN apk add --no-cache \
    git zip unzip icu-dev oniguruma-dev libpng-dev libjpeg-turbo-dev libwebp-dev libzip-dev autoconf build-base \
 &amp;&amp; docker-php-ext-configure gd --with-jpeg --with-webp \
 &amp;&amp; docker-php-ext-install -j$(nproc) pdo_mysql intl mbstring gd zip exif bcmath opcache

# Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html</code></pre>



<h2 class="wp-block-heading"><span id="toc4">Nginx の設定</span></h2>



<p><strong>ファイル:</strong> <code>C:\Work\Workspace\Docker\example.com\docker\nginx\default.conf</code></p>



<pre class="wp-block-code"><code>server {
  listen 80;
  server_name example.com localhost;

  root /var/www/html/web;
  index index.php index.html;

  location / {
    try_files $uri $uri/ /index.php?$args;
  }

  location ~ \.php$ {
    include       fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass php:9000;
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
  }

  location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2?|ttf)$ {
    expires 7d;
    add_header Cache-Control "public";
  }
}</code></pre>



<h2 class="wp-block-heading"><span id="toc5">php.ini の最低限の調整</span></h2>



<p><strong>ファイル:</strong> <code>C:\Work\Workspace\Docker\example.com\docker\php\php.ini</code></p>



<pre class="wp-block-code"><code>memory_limit = ${PHP_MEMORY_LIMIT}
max_execution_time = ${PHP_MAX_EXECUTION_TIME}
upload_max_filesize = 32M
post_max_size = 32M
date.timezone = Asia/Tokyo</code></pre>



<h2 class="wp-block-heading"><span id="toc6">コンテナの起動と初期化</span></h2>



<p><strong>PowerShell</strong> で次を実行します。</p>



<pre class="wp-block-code"><code>cd C:\Work\Workspace\Docker\example.com
# 初回ビルド＆起動
docker compose up -d --build

# 状態確認
docker compose ps</code></pre>



<ul class="wp-block-list">
<li><code>http://localhost:8080</code> → Nginx（Yii2はまだ未導入なので404/エラー想定）</li>



<li><code>http://localhost:8081</code> → phpMyAdmin（<code>root</code> / <code>root</code>、サーバ: <code>db</code> でログイン可）</li>



<li><code>http://localhost:8025</code> → Mailpit（受信ボックスUI）</li>
</ul>



<h2 class="wp-block-heading"><span id="toc7">Yii2 のインストール（コンテナ内でComposer実行）</span></h2>



<p><code>htdocs</code> に Yii2 Basic を展開します。</p>



<pre class="wp-block-code"><code># PHPコンテナに入る
docker compose exec php sh

# コンテナ内で実行（/var/www/html）
composer create-project yiisoft/yii2-app-basic .
exit</code></pre>



<p>作成後、Windows側では <code>C:\Work\Workspace\Docker\example.com\htdocs</code> にファイルが展開されます。Nginx の <code>root</code> は <code>/web</code> 配下なので、<code>web/index.php</code> が入口になります。</p>



<h2 class="wp-block-heading"><span id="toc8">DB接続設定（.env と Yii2設定）</span></h2>



<p>Yii2 Basic はデフォルトで <code>.env</code> はありませんが、設定を分けたい場合は導入も可能です。ここではシンプルに <code>config/db.php</code> を直接編集します。</p>



<p><strong>ファイル:</strong> <code>htdocs\config\db.php</code></p>



<pre class="wp-block-code"><code>&lt;?php
return &#91;
  'class' => 'yii\db\Connection',
  'dsn' => 'mysql:host=db;port=3306;dbname=example',
  'username' => 'app',
  'password' => 'apppass',
  'charset' => 'utf8mb4',
  'attributes' => &#91;
    PDO::ATTR_EMULATE_PREPARES => false,
    PDO::ATTR_STRINGIFY_FETCHES => false,
  ],
];</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><code>host</code> は <code><strong>db</strong></code>（docker-compose のサービス名）を指定します。ホストOSから直接接続する場合は <code>localhost:3307</code> です。</p>
</blockquote>



<p>初期テーブルを作る例として、マイグレーションを1本作ってみます（任意）。</p>



<pre class="wp-block-code"><code># PHPコンテナに入る
docker compose exec php sh

# マイグレーション作成
php yii migrate/create create_post_table

# 生成されたファイル(例: migrations/mYYYYMMDD_HHMMSS_create_post_table.php)を編集
exit</code></pre>



<p>サンプル（生成ファイルを編集）</p>



<pre class="wp-block-code"><code>public function safeUp()
{
  $this->createTable('{{%post}}', &#91;
    'id' => $this->primaryKey(),
    'title' => $this->string()->notNull(),
    'body' => $this->text(),
    'created_at' => $this->dateTime()->defaultExpression('CURRENT_TIMESTAMP'),
  ]);
}


public function safeDown()
{
  $this->dropTable('{{%post}}');
}</code></pre>



<pre class="wp-block-code"><code># もう一度入って実行
docker compose exec php sh
php yii migrate --interactive=0
exit</code></pre>



<h2 class="wp-block-heading"><span id="toc9">Mailpit（メール送信テスト）設定</span></h2>



<p>開発中のメールは <strong>本当に送らない</strong> のが安全です。Mailpit に流してUIで確認しましょう。</p>



<p><strong>ファイル:</strong> <code>htdocs\config\web.php</code>（<code>components</code> に <code>mailer</code> を追記）</p>



<pre class="wp-block-code"><code>'components' => &#91;
  // ... 既存設定 ...
  'mailer' => &#91;
    'class' => 'yii\swiftmailer\Mailer',
    'useFileTransport' => false, // falseでSMTPへ送信
    'transport' => &#91;
      'class' => 'Swift_SmtpTransport',
      'host' => 'mailpit',
      'port' => 1025,
      'encryption' => null,
    ],
  ],
],</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>もし Yii2 を <code>yiisoft/mailer</code> に置き換える場合は適宜設定を読み替えてください（SwiftMailerは非推奨化済みですが、Yii2 Basic既定の形のままでもMailpit連携は可能です）。</p>
</blockquote>



<p>テスト送信例（コントローラやコンソールから）</p>



<pre class="wp-block-code"><code>Yii::$app->mailer->compose()
         ->setFrom('no-reply@example.com')
         ->setTo('test@example.com')
         ->setSubject('Mailpit送信テスト')
         ->setTextBody('これはテスト本文です')
         ->send();</code></pre>



<p><code>http://localhost:8025</code> を開くと、受信メールが一覧表示されます。</p>



<h2 class="wp-block-heading"><span id="toc10">動作確認（Web・DB・Mail）</span></h2>



<ol class="wp-block-list">
<li><strong>Web</strong><br><code>http://localhost:8080</code> にアクセスして Yii2 のトップが表示されること。</li>



<li><strong>DB</strong><br><code>http://localhost:8081</code> → phpMyAdmin に <code>root/root</code> でログイン。<code>example</code> データベースに <code>post</code> テーブルができていること。</li>



<li><strong>Mail</strong><br>サンプルコードを実行し、<code>http://localhost:8025</code> の受信箱にメールが入ること。</li>
</ol>



<h2 class="wp-block-heading"><span id="toc11">トラブルシューティング</span></h2>



<h4 class="wp-block-heading"><span id="toc12">ポート競合</span></h4>



<p><code>8080</code>/<code>8081</code>/<code>8025</code>/<code>1025</code>/<code>3307</code> が使用中 → <code>docker-compose.yml</code> の <code>ports</code> 左側（ホスト側）を変更。</p>



<h4 class="wp-block-heading"><span id="toc13">MySQLへ接続できない</span></h4>



<ul class="wp-block-list">
<li><code>host</code> は <code><strong>db</strong></code>（Docker内部）か、ホスト接続では <code>localhost:3307</code> を指定。</li>



<li>初回起動直後はDBの立ち上がり待ちが必要。数秒待って再試行。</li>
</ul>



<h4 class="wp-block-heading"><span id="toc14">Windows で権限由来の書き込みエラー</span></h4>



<p><code>htdocs/runtime</code> と <code>htdocs/web/assets</code> の書き込み権限が必要。コンテナ側で <code>chmod -R 777 runtime web/assets</code>（開発用途限定）。</p>



<h4 class="wp-block-heading"><span id="toc15">ファイルの改行コード</span></h4>



<p>Nginxやシェル用ファイルは <strong>LF</strong> を推奨。VS Codeで <code>LF</code> へ変換。</p>



<h4 class="wp-block-heading"><span id="toc16">古いコンテナやイメージの削除でエラー</span></h4>



<p>例: <code>Error response from daemon: conflict: unable to delete ... image is being used by stopped container ...</code></p>



<pre class="wp-block-code"><code>docker ps -a # 停止中を含め一覧
docker rm &lt;CONTAINER_ID> # 停止中コンテナを削除
docker rmi &lt;IMAGE_ID> # 参照がなくなったらイメージ削除
# 一括停止・削除（このプロジェクト内）
docker compose down -v # コンテナ・ネットワーク・ボリューム削除
docker system prune -f # 不要なリソース掃除</code></pre>



<h4 class="wp-block-heading"><span id="toc17">Composerが遅い/タイムアウト</span></h4>



<p>一時的に <code>-vvv</code> で状況確認。社内プロキシ下では環境変数の設定を。</p>



<h2 class="wp-block-heading"><span id="toc18">よく使うコマンド集</span></h2>



<pre class="wp-block-code"><code># 起動・ビルド
cd C:\Work\Workspace\Docker\example.com
docker compose up -d --build

# 停止
docker compose down

# 停止＋ボリュームごと削除（DB初期化したいとき）
docker compose down -v

# ログ参照
docker compose logs -f nginx
docker compose logs -f php
docker compose logs -f db

# コンテナに入る
docker compose exec php sh

# 権限（開発用）
docker compose exec php sh -c "chmod -R 777 runtime web/assets"</code></pre>



<h2 class="wp-block-heading"><span id="toc19">あとがき</span></h2>



<p>ここまでで、<strong>Windows + Docker</strong> 上に <strong>Yii2 + MySQL + phpMyAdmin + Mailpit</strong> の開発環境が整いました。実運用では Mailpit の代わりに本番SMTPを使いますが、開発段階では誤送信防止のため <strong>Mailpit固定</strong> を強くおすすめします。また、MySQLのパスワードや公開ポートは本番用に必ず見直してください。必要に応じて <strong>SSL</strong> や <strong>Xdebug</strong> の導入、<strong>Nginxのキャッシュ/セキュリティヘッダ</strong> の調整などを行うと、より快適で安全な環境になります。</p>



<div class="wp-block-cocoon-blocks-blank-box-1 blank-box block-box">
<h5 class="wp-block-heading"><span id="toc20">引用元</span></h5>



<ul class="wp-block-list">
<li>Yii Framework 公式ドキュメント（Yii2 Basicテンプレート）<br><a rel="noopener" href="https://www.yiiframework.com/doc/guide/2.0/ja" target="_blank">https://www.yiiframework.com/doc/guide/2.0/ja</a></li>



<li>Docker 公式ドキュメント<br><a rel="noopener" href="https://docs.docker.com/" target="_blank">https://docs.docker.com/</a></li>



<li>Docker Compose 公式ドキュメント<br><a rel="noopener" href="https://docs.docker.com/compose/" target="_blank">https://docs.docker.com/compose/</a></li>



<li>MySQL 公式ドキュメント<br><a rel="noopener" href="https://dev.mysql.com/doc/" target="_blank">https://dev.mysql.com/doc/</a></li>



<li>phpMyAdmin 公式サイト<br><a rel="noopener" href="https://www.phpmyadmin.net/" target="_blank">https://www.phpmyadmin.net/</a></li>



<li>Mailpit（開発用SMTP &amp; Web UIツール）公式リポジトリ<br><a rel="noopener" href="https://github.com/axllent/mailpit" target="_blank">https://github.com/axllent/mailpit</a></li>



<li>Nginx 公式ドキュメント<br><a href="https://nginx.org/en/docs/">https://nginx.org/en/docs/</a></li>



<li>PHP 公式マニュアル（Docker Hub版）<br><a rel="noopener" href="https://hub.docker.com/_/php" target="_blank">https://hub.docker.com/_/php</a></li>



<li>Composer 公式サイト<br><a rel="noopener" href="https://getcomposer.org/" target="_blank">https://getcomposer.org/</a></li>
</ul>
</div>



<p></p>



<p></p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/build-your-yii2-development-environment-with-docker-in-no-time-a-beginners-guide-to-integrating-mysql-phpmyadmin-and-mailpit/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Yii3ついに登場！Yii2からどう変わった？進化点と基本構造、サンプルを一挙解説</title>
		<link>https://blog.takeho.com/yii3-is-finally-here-evolution-basic-structure-and-samples-at-a-glance/</link>
					<comments>https://blog.takeho.com/yii3-is-finally-here-evolution-basic-structure-and-samples-at-a-glance/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Fri, 04 Jul 2025 11:26:00 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[DI]]></category>
		<category><![CDATA[PSR]]></category>
		<category><![CDATA[Yii3]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=1206</guid>

					<description><![CDATA[PHPの人気フレームワーク「Yii2」の後継として、長らく開発が続けられていた「Yii3」がついにリリース間近となりました。公式ガイド（https://yii3.netlify.app/guide.html）も整備されつ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>PHPの人気フレームワーク「Yii2」の後継として、長らく開発が続けられていた「Yii3」がついにリリース間近となりました。<br>公式ガイド（<a class="" href="https://yii3.netlify.app/guide.html">https://yii3.netlify.app/guide.html</a>）も整備されつつあり、Yii2ユーザーやこれからPHPフレームワークを選ぼうとしている方にとって注目のタイミングです。</p>



<p>本記事では、Yii3で何が変わったのか、Yii2との違いやディレクトリ構造、実際にデータベースを使ったミニサンプルも交えて、実用的に解説します。</p>





<a rel="noopener" href="https://yii3.netlify.app/guide.html" title="https://yii3.netlify.app/guide.html" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img decoding="async" src="https://s.wordpress.com/mshots/v1/https%3A%2F%2Fyii3.netlify.app%2Fguide.html?w=160&#038;h=90" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">https://yii3.netlify.app/guide.html</div><div class="blogcard-snippet external-blogcard-snippet"></div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://yii3.netlify.app/guide.html" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">yii3.netlify.app</div></div></div></div></a>





  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-6"><label class="toc-title" for="toc-checkbox-6">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">Yii2との主な違い・進化ポイント</a></li><li><a href="#toc2" tabindex="0">Yii3のディレクトリ構成</a></li><li><a href="#toc3" tabindex="0">Yii3での簡単なデータベース操作サンプル（MVC構成で作成）</a><ol><li><a href="#toc4" tabindex="0">ディレクトリ構成とファイル配置</a></li><li><a href="#toc5" tabindex="0">モデル（M） – src/Model/Post.php</a></li><li><a href="#toc6" tabindex="0">コントローラ（C） – src/Controller/SiteController.php</a></li><li><a href="#toc7" tabindex="0">ビュー（V） – src/View/site/index.php</a></li><li><a href="#toc8" tabindex="0">ルーティング設定 – config/routes.php</a></li><li><a href="#toc9" tabindex="0">アプリ設定 – config/web.php</a></li><li><a href="#toc10" tabindex="0">フロントコントローラ – public/index.php</a></li><li><a href="#toc11" tabindex="0">MySQL テーブル定義</a></li><li><a href="#toc12" tabindex="0">実行までの流れまとめ</a></li></ol></li><li><a href="#toc13" tabindex="0">補足：Yii3は「自由度の高いMVC」</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">Yii2との主な違い・進化ポイント</span></h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>項目</th><th>Yii2</th><th>Yii3</th></tr></thead><tbody><tr><td>リリース形態</td><td>モノリシック構造</td><td>パッケージ分割（コンポーザ管理）</td></tr><tr><td>DI（依存性注入）</td><td>独自コンテナ</td><td>PSR-11準拠のDIコンテナ</td></tr><tr><td>イベントシステム</td><td>グローバル依存</td><td>より明確なスコープ管理</td></tr><tr><td>HTTP処理</td><td>Yii独自実装</td><td>PSR-7/PSR-15完全対応</td></tr><tr><td>テンプレートエンジン</td><td>PHPベース（Twig等も可）</td><td>Twig対応強化、Templateパッケージ分離</td></tr><tr><td>ルーティング</td><td>独自実装</td><td>PSR準拠、Middleware対応</td></tr><tr><td>テスト性</td><td>構造がやや閉じていた</td><td>モジュール化されテストしやすく</td></tr><tr><td>コマンドライン</td><td>yiiコマンド一体型</td><td>独立したパッケージに分離（symfony/console）</td></tr></tbody></table></figure>



<p>Yii3では、近年のPHP界のトレンドであるPSR準拠を徹底しており、<strong>モダンPHPと高い互換性</strong>を持ちながら設計されています。</p>



<h2 class="wp-block-heading"><span id="toc2">Yii3のディレクトリ構成</span></h2>



<p>Yii3の標準的なアプリケーション構造は以下のようになります。</p>



<pre class="wp-block-preformatted">myapp/<br>├── config/          ← アプリ設定（DIやルーティングなど）<br>├── public/          ← Web公開ディレクトリ（index.php）<br>├── runtime/         ← ログやキャッシュなどの一時ファイル<br>├── src/             ← アプリケーションの本体コード<br>│   └── Controller/<br>│   └── Middleware/<br>│   └── View/<br>├── tests/           ← PHPUnitベースのテストコード<br>├── vendor/          ← Composer依存<br>└── composer.json</pre>



<p>「config」や「src」にアプリロジックが集約されており、明確にMVCが分離されています。</p>



<h2 class="wp-block-heading"><span id="toc3">Yii3での簡単なデータベース操作サンプル（MVC構成で作成）</span></h2>



<p>このサンプルでは、次の機能を実装します。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>「<code>post</code> テーブルの全件を取得して、一覧表示するWebページ」</p>
</blockquote>



<h3 class="wp-block-heading"><span id="toc4">ディレクトリ構成とファイル配置</span></h3>



<p>まず、以下のようにディレクトリ構成を整理します。Yii3では、<code>src/</code> がアプリケーションコードの中核です。</p>



<pre class="wp-block-code"><code>myapp/
├── config/
│   └── params.php
│   └── routes.php         ← ルーティング設定
│   └── web.php            ← DI・アプリ設定
├── src/
│   ├── Controller/
│   │   └── SiteController.php   ← コントローラ（C）
│   ├── Model/
│   │   └── Post.php             ← モデル（M）
│   ├── View/
│   │   └── site/
│   │       └── index.php        ← ビュー（V）
├── public/
│   └── index.php          ← フロントコントローラ
├── vendor/                ← Composer依存
└── composer.json</code></pre>



<h3 class="wp-block-heading"><span id="toc5">モデル（M） – src/Model/Post.php</span></h3>



<p>ActiveRecordを使用して、<code>post</code> テーブルに対応したモデルクラスを作成します。</p>



<pre class="wp-block-code"><code>&lt;?php
namespace App\Model;

use Yiisoft\ActiveRecord\ActiveRecord;

final class Post extends ActiveRecord
{
    public static function tableName(): string
    {
        return 'post';
    }
}</code></pre>



<h3 class="wp-block-heading"><span id="toc6">コントローラ（C） – src/Controller/SiteController.php</span></h3>



<p>データベースからデータを取得し、ビューに渡す役割を担います。</p>



<pre class="wp-block-code"><code>&lt;?php
namespace App\Controller;

use App\Model\Post;
use Yiisoft\Yii\View\ViewRenderer;
use Yiisoft\Router\CurrentRoute;

final class SiteController
{
    private ViewRenderer $view;

    public function __construct(ViewRenderer $view)
    {
        $this->view = $view->withControllerName('site');
    }

    public function index(): string
    {
        $posts = Post::find()->all(); // すべての投稿を取得
        return $this->view->render('index', &#91;'posts' => $posts]);
    }
}</code></pre>



<h3 class="wp-block-heading"><span id="toc7">ビュー（V） – src/View/site/index.php</span></h3>



<p>データをHTMLとして整形・表示するテンプレートファイルです。</p>



<pre class="wp-block-code"><code>&lt;h1>記事一覧&lt;/h1>

&lt;ul>
&lt;?php foreach ($posts as $post): ?>
    &lt;li>
        &lt;strong>&lt;?= htmlspecialchars($post->title) ?>&lt;/strong>&lt;br>
        &lt;?= nl2br(htmlspecialchars($post->content)) ?>
    &lt;/li>
&lt;?php endforeach; ?>
&lt;/ul></code></pre>



<h3 class="wp-block-heading"><span id="toc8">ルーティング設定 – config/routes.php</span></h3>



<p>リクエストURLとコントローラの対応関係を定義します。</p>



<pre class="wp-block-code"><code>&lt;?php

use Yiisoft\Router\Route;
use App\Controller\SiteController;

return &#91;
    Route::get('/')
        ->action(&#91;SiteController::class, 'index'])
];</code></pre>



<h3 class="wp-block-heading"><span id="toc9">アプリ設定 – config/web.php</span></h3>



<p>必要なパッケージや設定を読み込むファイルです。ここでDB接続なども設定します。</p>



<pre class="wp-block-code"><code>&lt;?php

use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Mysql\Connection;

return &#91;
    ConnectionInterface::class => static function () {
        return new Connection(
            dsn: 'mysql:host=localhost;dbname=yii3_demo',
            username: 'root',
            password: 'your_password',
        );
    },
];</code></pre>



<h3 class="wp-block-heading"><span id="toc10">フロントコントローラ – public/index.php</span></h3>



<p>アプリケーションのエントリーポイントです。</p>



<pre class="wp-block-code"><code>&lt;?php

declare(strict_types=1);

require dirname(__DIR__) . '/vendor/autoload.php';

use Yiisoft\Yii\Web\Application;
use Yiisoft\Yii\Web\Emitter\SapiEmitter;

$container = require dirname(__DIR__) . '/config/web.php';

$app = new Application($container);

$response = $app->handle(
    $_SERVER&#91;'REQUEST_METHOD'],
    $_SERVER&#91;'REQUEST_URI']
);

(new SapiEmitter())->emit($response);</code></pre>



<h3 class="wp-block-heading"><span id="toc11">MySQL テーブル定義</span></h3>



<pre class="wp-block-code"><code>CREATE TABLE post (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL
);</code></pre>



<h3 class="wp-block-heading"><span id="toc12">実行までの流れまとめ</span></h3>



<ol class="wp-block-list">
<li>MySQLで <code>post</code> テーブルを作成する</li>



<li><code>composer install</code> で依存パッケージを取得</li>



<li><code>php -S localhost:8080 -t public</code> で開発サーバを起動</li>



<li>ブラウザで <code>http://localhost:8080</code> にアクセス</li>
</ol>



<h2 class="wp-block-heading"><span id="toc13">補足：Yii3は「自由度の高いMVC」</span></h2>



<p>Yii3は、Laravelのような「レールに乗った」MVCよりも、より<strong>柔軟で明示的なアーキテクチャ</strong>を採用しています。自分で組み立てる分、学習コストはやや高いかもしれませんが、カスタマイズ性と保守性に優れた構成です。</p>



<p>この構成に沿えば、<strong>MVCモデルの設計思想を維持しつつ、Yii3のモダンな利点</strong>を活かしたWebアプリを構築できます。<br>今後はフォームバリデーション、APIレスポンス、ログイン機能など、より実践的なトピックも記事化していきます。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/yii3-is-finally-here-evolution-basic-structure-and-samples-at-a-glance/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Yii2でメールサーバから受信ボックスのデータを取得</title>
		<link>https://blog.takeho.com/retrieve-inbox-data-from-mail-server-with-yii2/</link>
					<comments>https://blog.takeho.com/retrieve-inbox-data-from-mail-server-with-yii2/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Tue, 04 Feb 2025 14:41:00 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[PHP IMAP]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=608</guid>

					<description><![CDATA[Yii2でGmailやYahooメールを受信するコンポーネントを作成してみました。 目次 コンポーネントの開発ディレクトリ・ファイルの作成ファイルの作成使い方設定実行例InboxControllerViewファイルブラウ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Yii2でGmailやYahooメールを受信するコンポーネントを作成してみました。</p>



<div class="wp-block-cocoon-blocks-tab-caption-box-1 tab-caption-box block-box not-nested-style cocoon-block-tab-caption-box"><div class="tab-caption-box-label block-box-label box-label"><span class="tab-caption-box-label-text block-box-label-text box-label-text">注意事項</span></div><div class="tab-caption-box-content block-box-content box-content">
<p>PHP IMAP関数が有効である必要があります。</p>
</div></div>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-8"><label class="toc-title" for="toc-checkbox-8">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">コンポーネントの開発</a><ol><li><a href="#toc2" tabindex="0">ディレクトリ・ファイルの作成</a></li><li><a href="#toc3" tabindex="0">ファイルの作成</a></li></ol></li><li><a href="#toc4" tabindex="0">使い方</a><ol><li><a href="#toc5" tabindex="0">設定</a></li><li><a href="#toc6" tabindex="0">実行例</a><ol><li><a href="#toc7" tabindex="0">InboxController</a></li><li><a href="#toc8" tabindex="0">Viewファイル</a></li><li><a href="#toc9" tabindex="0">ブラウザで確認</a></li></ol></li></ol></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">コンポーネントの開発</span></h2>



<h3 class="wp-block-heading"><span id="toc2">ディレクトリ・ファイルの作成</span></h3>



<p>アプリケーションディレクトリ内に<strong>components</strong>ディレクトリを作成します。</p>



<p>次にそのディレクトリの中に<strong>MailFetcherComponent.php</strong>のファイルを次の内容で作成します。</p>



<h3 class="wp-block-heading"><span id="toc3">ファイルの作成</span></h3>



<pre class="wp-block-code"><code>&lt;?php

namespace app\components;
    
use Yii;
use yii\base\Component;
use yii\base\Exception;

class MailFetcherComponent extends Component
{
    // Kind ( SMTP / IMAP / POP3 ).
    public $kind;
    
    // Mail server.
    public $host;
    
    // Connect post.
    public $port;
    
    // Account user.
    public $username;
    
    // Account password.
    public $password;
    
    // Encrypt type ( PLAIN / LOGIN / CRAM-MD5 ).
    public $encryption;
    
    // Target mail folder.
    public $mailboxFolder = 'INBOX';
    
    // Seaving server directoy for attachments.
    public $attachmentPath = false;
    
    protected $inbox;
    
    public function init()
    {
        parent::init();
        
        if (!$this->host || !$this->username || !$this->password) {
            throw  new \Exception("メールサーバの情報が不足しています。");
        }
        
    }
    
    public function connectOpen($args = &#91;])
    {
        $labels = &#91; 'kind', 'host', 'port', 
                    'encryption', 'mailboxFolder'];
        
        $connectSource = "{{host}:{port}/{kind}/{encryption}}{mailboxFolder}";
        
        foreach ($labels as $label){
            if (isset($args&#91;$label])) {
                $this->$label = $args&#91;$label];
            }
            if (in_array($label, &#91;'username', 'password'])) continue;
            
            $val = $label == 'mailboxFolder' ? 
                    strtoupper($this->$label) : 
                    strtolower($this->$label); 
            
            $connectSource = str_replace('{'.$label.'}', $val, $connectSource);
        }

        $this->inbox = imap_open($connectSource, $this->username, $this->password);
        
        if (!$this->inbox) {
            echo "IMAP接続に失敗しました: " . imap_last_error();
            return;
        }
        
        if (!$this->attachmentPath) {
            $this->attachmentPath = Yii::getAlias('@runtime/mail_attachments');
        }
        
        if (!is_dir($this->attachmentPath)) {
            mkdir($this->attachmentPath, 0777, true);
        }
    }
    
    public function fetchMails($searchCriteria = 'ALL')
    {
        $sources = &#91;];
        
        $emails = imap_search($this->inbox, $searchCriteria);
        
        if ($emails) 
        {
            rsort($emails); // 最新のメールが最初に表示されるようにソート

            foreach ($emails as $emailNumber) 
            {
                $overview = imap_fetch_overview($this->inbox, $emailNumber, 0);
                
                // サブジェクトのデコード
                $subject = $this->mimeDecode($overview&#91;0]->subject);

                // 差出人のデコード
                $from = $this->mimeDecode($overview&#91;0]->from);
                
                $structure = imap_fetchstructure($this->inbox, $emailNumber);
                $message = '';
                
                
                if ($structure->type == 1) { // マルチパートメールの場合
                    
                    $attachments = array();
                    foreach ($structure->parts as $partNumber => $part) {
                        if ($part->subtype == 'PLAIN') {
                            $message = imap_fetchbody($this->inbox, $emailNumber, $partNumber + 1);

                            if ($part->encoding == 3) { // BASE64
                                $message = base64_decode($message);
                            } elseif ($part->encoding == 4) { // QUOTED-PRINTABLE
                                $message = quoted_printable_decode($message);
                            }
                            break;
                        }
                        
                        // 添付ファイルの取得
                        if (isset($part->disposition) &amp;&amp; strtolower($part->disposition) == 'attachment') {
                            $attachment = imap_fetchbody($this->inbox, $emailNumber, $partNumber + 1);

                            if ($part->encoding == 3) { // BASE64
                                $attachment = base64_decode($attachment);
                            } elseif ($part->encoding == 4) { // QUOTED-PRINTABLE
                                $attachment = quoted_printable_decode($attachment);
                            }

                            $filename = 'attachment_' . time() . '_' . ($part->dparameters&#91;0]->value ?? 'unknown');
                            file_put_contents($this->attachmentPath . '/' . $filename, $attachment);
                            $attachments&#91;] = $this->attachmentPath . '/' . $filename;
                            echo "添付ファイルを保存しました: " . $filename . "\n";
                        }
                    }
                } else { // 単一パートメールの場合
                    $message = imap_fetchbody($this->inbox, $emailNumber, 1);

                    // エンコードの処理
                    if ($structure->encoding == 3) { // BASE64
                        $message = base64_decode($message);
                    } elseif ($structure->encoding == 4) { // QUOTED-PRINTABLE
                        $message = quoted_printable_decode($message);
                    }
                }

                $sources&#91;$emailNumber] = &#91;
                    'Subject' => $subject,
                    'From' => $from,
                    'Date' => $overview&#91;0]->date,
                    'Message' => $message,
                ];
            }
        }
        
        imap_close($this->inbox);
        
        return $sources;
    }
    
    private function mimeDecode($str = '')
    {
        $encode_array = isset($str) ? imap_mime_header_decode($str) : &#91;];
        $decoded      = '';
        foreach ($encode_array as $part) {
            $decoded .= $part->text;
        }
        
        return $decoded;
    }   
}</code></pre>



<h2 class="wp-block-heading"><span id="toc4">使い方</span></h2>



<h3 class="wp-block-heading"><span id="toc5">設定</span></h3>



<p>設定ファイル（config/web.php）に作成したMailFetcherコンポーネントを次のように追加します。</p>



<pre class="wp-block-code"><code>    'components' => &#91;
        'mailFetcher' => &#91;
            'class' => 'app\components\MailFetcherComponent',
            'kind' => 'IMAP',
            'host' => 'メールサーバホスト名',  // IMAPサーバーのホスト名
            'username' => 'アカウントユーザー名',
            'password' => 'パスワード',
            'port' => 'ポート',
            'encryption' => '暗号化タイプ',
            'mailboxFolder' => 'INBOX',  // デフォルトでINBOXを使用
        ],</code></pre>



<p>上記の設定でコンポーネントをコントローラー上で実行できるようになります。</p>



<pre class="wp-block-code"><code>Yii::$app->mailFetcher;</code></pre>



<h3 class="wp-block-heading"><span id="toc6">実行例</span></h3>



<h4 class="wp-block-heading"><span id="toc7">InboxController</span></h4>



<p>InboxControllerを次のように作成します。</p>



<pre class="wp-block-code"><code>&lt;?php

namespace app\controllers;

use Yii;
use app\models\Account;

class InboxController extends \yii\web\Controller
{
    public function actionIndex()
    {
        $receiver= Yii::$app->mailFetcher;
        
        $receiver->connectOpen();
        
        return $this->render('index', &#91;
            'receiver' => $receiver->fetchMails('ALL'),
        ]);
    }
}</code></pre>



<h4 class="wp-block-heading"><span id="toc8">Viewファイル</span></h4>



<p><strong>/views/inbox/index.php</strong>を次にように編集します。</p>



<pre class="wp-block-code"><code>&lt;?php
/** @var yii\web\View $this */
?>
&lt;h1>inbox/index&lt;/h1>

&lt;p>
    You may change the content of this page by modifying
    the file &lt;code>&lt;?= __FILE__; ?>&lt;/code>.
&lt;/p>
&lt;h2>Receiver Result&lt;/h2>

&lt;?php foreach($receiver as $email): ?>

&lt;div style="padding:1em;margin-bottom:3em;border:solid 3px #999;">
    &lt;dl>
        &lt;dt>Date&lt;/dt>
        &lt;dd>&lt;?php echo $email&#91;'Date'] ?>&lt;/dd>
        &lt;dt>From&lt;/dt>
        &lt;dd>&lt;?php echo $email&#91;'From'] ?>&lt;/dd>
        &lt;dt>Subject&lt;/dt>
        &lt;dd>&lt;?php echo $email&#91;'Subject'] ?>&lt;/dd>
        &lt;dt>Message&lt;/dt>
        &lt;dd>&lt;?php echo nl2br($email&#91;'Message']) ?>&lt;/dd>
    &lt;/dl>
&lt;/div>
&lt;?php endforeach; ?></code></pre>



<h4 class="wp-block-heading"><span id="toc9">ブラウザで確認</span></h4>



<p>次のURLへアクセスして確認します。</p>



<pre class="wp-block-code"><code>http:&#47;&#47;ホスト名/index.php?r=inbox/index</code></pre>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="1000" height="683" src="https://blog.takeho.com/wp-content/uploads/2025/02/3483292.png" alt="" class="wp-image-615" srcset="https://blog.takeho.com/wp-content/uploads/2025/02/3483292.png 1000w, https://blog.takeho.com/wp-content/uploads/2025/02/3483292-640x437.png 640w, https://blog.takeho.com/wp-content/uploads/2025/02/3483292-768x525.png 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure>



<p>メールの受信ボックス情報が確認できれば成功です。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/retrieve-inbox-data-from-mail-server-with-yii2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Yii2でFullCalendarを簡単に導入する方法</title>
		<link>https://blog.takeho.com/how-to-easily-implement-fullcalendar-in-yii2/</link>
					<comments>https://blog.takeho.com/how-to-easily-implement-fullcalendar-in-yii2/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Wed, 11 Dec 2024 03:03:00 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[Extension]]></category>
		<category><![CDATA[FullCalendar]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=579</guid>

					<description><![CDATA[Yii2フレームワークを使用して開発していると、カレンダーを使ったイベント管理が必要になることがあります。そのような場合に便利なツールが、JavaScriptベースのライブラリであるFullCalendarです。本記事で [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Yii2フレームワークを使用して開発していると、カレンダーを使ったイベント管理が必要になることがあります。そのような場合に便利なツールが、JavaScriptベースのライブラリである<strong>FullCalendar</strong>です。本記事では、FullCalendarをYii2プロジェクトに簡単に導入し、基本的なカレンダー表示を実現する方法をご紹介します。</p>



<h2 class="wp-block-heading">FullCalendarとは</h2>



<p>FullCalendarは、イベントのスケジュールやカレンダー表示を簡単に実装できる人気のJavaScriptライブラリです。レスポンシブ対応やさまざまなカスタマイズオプションを備えており、Googleカレンダーのような体験を提供できます。</p>



<h2 class="wp-block-heading">Yii2プロジェクトへの導入手順</h2>



<h3 class="wp-block-heading">拡張機能からインポート</h3>



<p>「yiitwofullcalendar」は、Yii2でFullCalendarを手軽に扱うための拡張です。これを使用することで、イベントの表示やカレンダーの基本的な設定が簡単に行えます。</p>



<p>Composerを使用して「yiitwofullcalendar」をインストールします。</p>



<pre class="wp-block-code"><code>php composer.phar require edofre/yii2-fullcalendar "@dev"</code></pre>



<p>Composerが依存関係を解決してインストールを完了したら、すぐに利用できます。</p>



<h3 class="wp-block-heading">カレンダーの表示</h3>



<p>次に、カレンダーを表示する基本的なコードを用意します。ここでは、<code>site/index</code>アクションでカレンダーを表示する例を示します。</p>



<h4 class="wp-block-heading">コントローラーの設定</h4>



<p><code><strong>controllers/SiteController.php</strong></code>で、イベントデータを渡す処理を記述します。</p>



<pre class="wp-block-code"><code>public function actionIndex()
{
    $events = &#91;
        &#91;
            'title' => 'イベント1',
            'start' => '2024-12-15',
        ],
        &#91;
            'title' => 'イベント2',
            'start' => '2024-12-18',
            'end' => '2024-12-20',
        ],
    ];

    return $this->render('index', &#91;'events' => $events]);
}</code></pre>



<h4 class="wp-block-heading">ビューの設定</h4>



<p><code><strong>views/site/index.php</strong></code>に、カレンダーを表示するコードを追加します。</p>



<pre class="wp-block-code"><code>&lt;?php
use yii2fullcalendar\yii2fullcalendar;

echo yii2fullcalendar::widget(&#91;
    'options' => &#91;
        'id' => 'calendar',
    ],
    'clientOptions' => &#91;
        'locale' => 'ja',
        'initialView' => 'dayGridMonth',
        'headerToolbar' => &#91;
            'left' => 'prev,next today',
            'center' => 'title',
            'right' => 'dayGridMonth,timeGridWeek,timeGridDay',
        ],
    ],
    'events' => $events, // コントローラーから渡されたイベントデータ
]);
?></code></pre>



<p>上記のコードでは、<code>events</code>キーに渡したデータがカレンダーに表示されます。</p>



<h2 class="wp-block-heading">カスタマイズ例</h2>



<h3 class="wp-block-heading">イベントのクリック処理を追加</h3>



<p>イベントをクリックした際にアラートを表示する機能を追加する例です。</p>



<pre class="wp-block-code"><code>'clientEvents' => &#91;
    'eventClick' => new \yii\web\JsExpression('function(event) {
        alert("イベントタイトル: " + event.title);
    }'),
],</code></pre>



<h3 class="wp-block-heading">Ajaxで動的にイベントを取得</h3>



<p>イベントを動的に取得するには、<code>events</code>キーにURLを指定します。</p>



<pre class="wp-block-code"><code>'events' => \yii\helpers\Url::to(&#91;'/event/get-events']),</code></pre>



<p>コントローラーで、指定したURLに対応するアクションを作成し、イベントデータを返します。</p>



<pre class="wp-block-preformatted">public function actionGetEvents()<br>{<br>    \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;<br>    return [<br>        [<br>            'title' => '動的イベント',<br>            'start' => date('Y-m-d'),<br>        ],<br>    ];<br>}</pre>



<h2 class="wp-block-heading">まとめ</h2>



<p>「yiitwofullcalendar」を使えば、Yii2プロジェクトでFullCalendarを簡単に利用できます。デフォルト機能を活用するだけでなく、カスタマイズすることで、より実用的なカレンダーを実装可能です。</p>



<p>スケジュール管理やイベント一覧を手軽に追加したい方は、ぜひ試してみてください！</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/how-to-easily-implement-fullcalendar-in-yii2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Bootstrap卒業宣言！Yii2でZurb Foundationを使う具体的ステップ！</title>
		<link>https://blog.takeho.com/declaration-of-bootstrap-graduation-concrete-steps-to-use-zurb-foundation-in-yii2/</link>
					<comments>https://blog.takeho.com/declaration-of-bootstrap-graduation-concrete-steps-to-use-zurb-foundation-in-yii2/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Sun, 24 Nov 2024 03:25:00 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[Foundation]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=550</guid>

					<description><![CDATA[Yii2 FrameworkでデフォルトのBootstrapを無効化し、Zurb Foundationを導入する具体的な方法を紹介します。Composerでのインストールからアセットバンドルの設定、レイアウトでの適用、J [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Yii2 FrameworkでデフォルトのBootstrapを無効化し、Zurb Foundationを導入する具体的な方法を紹介します。Composerでのインストールからアセットバンドルの設定、レイアウトでの適用、JavaScriptの初期化までをステップバイステップで解説。Foundationを使用してUIをカスタマイズし、モダンなデザインを実現する手順を簡潔にまとめています。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-10"><label class="toc-title" for="toc-checkbox-10">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">Foundationをインストールする</a></li><li><a href="#toc2" tabindex="0">Bootstrapを無効化する</a></li><li><a href="#toc3" tabindex="0">Foundationアセットを登録する</a><ol><li><a href="#toc4" tabindex="0">FoundationAssetを作成</a></li><li><a href="#toc5" tabindex="0">AppAssetで読み込む</a></li></ol></li><li><a href="#toc6" tabindex="0">FoundationのグリッドやUIコンポーネントを使用する</a></li><li><a href="#toc7" tabindex="0">FoundationのJavaScriptを有効化</a><ol><ol><li><a href="#toc8" tabindex="0">初期化スクリプト</a></li></ol></li></ol></li><li><a href="#toc9" tabindex="0">Foundationに基づいたスタイリングとレイアウトの調整</a></li><li><a href="#toc10" tabindex="0">Foundationを使うメリット</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">Foundationをインストールする</span></h2>



<p>FoundationをインストールするためにComposerを利用します。</p>



<pre class="wp-block-code"><code># composer require zurb/foundation</code></pre>



<p>または、直接FoundationのCSS/JSファイルをダウンロードして<code>web/css</code>や<code>web/js</code>ディレクトリに配置します。</p>



<h2 class="wp-block-heading"><span id="toc2">Bootstrapを無効化する</span></h2>



<p>Yii2アプリケーションでは、デフォルトでBootstrapが読み込まれている可能性があります。これを無効にするには、アプリケーションの設定ファイル<code><strong>config/web.php</strong></code>を編集します。</p>



<pre class="wp-block-code"><code>'components' => &#91;
    'assetManager' => &#91;
        'bundles' => &#91;
            'yii\bootstrap\BootstrapAsset' => false,
            'yii\bootstrap\BootstrapPluginAsset' => false,
        ],
    ],
],</code></pre>



<p>これにより、Bootstrapのアセットが読み込まれなくなります。</p>



<h2 class="wp-block-heading"><span id="toc3">Foundationアセットを登録する</span></h2>



<p>独自のアセットバンドルを作成してFoundationを登録します。</p>



<h3 class="wp-block-heading"><span id="toc4">FoundationAssetを作成</span></h3>



<p>以下のようなPHPファイルを<code>frontend/assets/FoundationAsset.php</code>（または適切な場所）に作成します。</p>



<pre class="wp-block-code"><code>namespace frontend\assets;

use yii\web\AssetBundle;

class FoundationAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = &#91;
        'css/foundation.min.css', // FoundationのCSSファイル
    ];
    public $js = &#91;
        'js/foundation.min.js', // FoundationのJSファイル
    ];
    public $depends = &#91;
        'yii\web\YiiAsset',
    ];
}</code></pre>



<p>Foundationのファイルパスは、ダウンロード先に応じて変更してください。</p>



<h3 class="wp-block-heading"><span id="toc5">AppAssetで読み込む</span></h3>



<p><code><strong>frontend/assets/AppAsset.php</strong></code>にFoundationAssetを依存関係として追加します。</p>



<pre class="wp-block-code"><code>namespace frontend\assets;

use yii\web\AssetBundle;

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = &#91;
        'css/site.css', // その他のCSS
    ];
    public $js = &#91;
        // 必要なJSファイル
    ];
    public $depends = &#91;
        'yii\web\YiiAsset',
        'frontend\assets\FoundationAsset', // 追加
    ];
}</code></pre>



<h2 class="wp-block-heading"><span id="toc6">FoundationのグリッドやUIコンポーネントを使用する</span></h2>



<p>レイアウトファイルやビューでFoundationのクラスや構造を利用します。</p>



<pre class="wp-block-code"><code>&lt;!DOCTYPE html>
&lt;html lang="&lt;?= Yii::$app->language ?>">
&lt;head>
    &lt;meta charset="&lt;?= Yii::$app->charset ?>">
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0">
    &lt;title>&lt;?= Html::encode($this->title) ?>&lt;/title>
    &lt;?php $this->head() ?>
&lt;/head>
&lt;body>
&lt;?php $this->beginBody() ?>

&lt;div class="grid-container">
    &lt;div class="grid-x grid-padding-x">
        &lt;div class="cell small-12 medium-8">
            &lt;?= $content ?>
        &lt;/div>
    &lt;/div>
&lt;/div>

&lt;?php $this->endBody() ?>
&lt;/body>
&lt;/html></code></pre>



<h2 class="wp-block-heading"><span id="toc7">FoundationのJavaScriptを有効化</span></h2>



<p>FoundationのJavaScriptコンポーネント（例えばモーダルやタブ）を利用するには、初期化スクリプトを追加します。</p>



<h4 class="wp-block-heading"><span id="toc8">初期化スクリプト</span></h4>



<p><code><strong>views/layouts/main.php</strong></code>のフッター部分に以下を追加します。</p>



<pre class="wp-block-code"><code>&lt;script>
    $(document).foundation();
&lt;/script></code></pre>



<h2 class="wp-block-heading"><span id="toc9">Foundationに基づいたスタイリングとレイアウトの調整</span></h2>



<p>ビューでBootstrapのクラスを使用している箇所をFoundationのクラスに置き換えます。例えば、<code>row</code>を<code>grid-x</code>に、<code>col-md-6</code>を<code>cell medium-6</code>に変更します。</p>



<p>これで、Yii2アプリケーションでFoundationを利用する準備が整います！</p>



<h2 class="wp-block-heading"><span id="toc10">Foundationを使うメリット</span></h2>



<p>Foundationを使うメリットとして挙げられるのは、<strong>「よりプロフェッショナルなデザイン表現が可能で、競合と差をつけられること」</strong>です。特に、カスタマイズ性やモダンなUIコンポーネントが豊富で、デザイン性を重視したいプロジェクトに最適です。</p>



<ol class="wp-block-list">
<li><strong>カスタマイズ性の高さ</strong><br>Foundationは柔軟なグリッドシステムやモジュール構造を持ち、デザインや機能をプロジェクトのニーズに応じて簡単に調整できます。</li>



<li><strong>レスポンシブデザインへの最適化</strong><br>Foundationはモバイルファーストのアプローチを強化しており、細かいレスポンシブ調整が可能です。</li>



<li><strong>現代的なUI/UXコンポーネント</strong><br>Foundationは「モダンな見た目」のコンポーネントが多く、Bootstrapよりも洗練されたデザインを提供します。</li>



<li><strong>差別化されたデザインが可能</strong><br>Bootstrapは多くのプロジェクトで使われているため、見た目が似てしまうことが多いですが、Foundationを使うことで独自性のあるUIが構築できます。</li>



<li><strong>拡張性と開発者支援</strong><br>Foundationは開発者向けツール（例えばモーションUIやアクセシビリティ機能）が充実しており、デザイナーや開発者にとって使いやすいフレームワークです。</li>
</ol>





<a rel="noopener" href="https://get.foundation" title="The most advanced responsive front-end framework in the world. | Foundation" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://s.wordpress.com/mshots/v1/https%3A%2F%2Fget.foundation?w=160&#038;h=90" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">The most advanced responsive front-end framework in the world. | Foundation</div><div class="blogcard-snippet external-blogcard-snippet"></div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://get.foundation" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">get.foundation</div></div></div></div></a>

]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/declaration-of-bootstrap-graduation-concrete-steps-to-use-zurb-foundation-in-yii2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Yii2でコンポーネントをカスタマイズする方法</title>
		<link>https://blog.takeho.com/hrp7l4b680m2xzd557ywbcfrl5ki68i3/</link>
					<comments>https://blog.takeho.com/hrp7l4b680m2xzd557ywbcfrl5ki68i3/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Sun, 17 Nov 2024 03:00:00 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[コンポーネント]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=538</guid>

					<description><![CDATA[Yii2のコンポーネントは、アプリケーション内で繰り返し使用する機能をカプセル化する便利な仕組みです。この記事では、実践的なサンプルコードを交えて、コンポーネントのカスタマイズ方法を詳しく解説します。 目次 カスタムコン [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Yii2のコンポーネントは、アプリケーション内で繰り返し使用する機能をカプセル化する便利な仕組みです。この記事では、実践的なサンプルコードを交えて、コンポーネントのカスタマイズ方法を詳しく解説します。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-12"><label class="toc-title" for="toc-checkbox-12">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">カスタムコンポーネントを作成する</a><ol><li><a href="#toc2" tabindex="0">コンポーネントファイルを作成</a></li><li><a href="#toc3" tabindex="0">コンポーネントをアプリケーションに登録する</a></li><li><a href="#toc4" tabindex="0">カスタムコンポーネントを使用する</a></li><li><a href="#toc5" tabindex="0">高度な設定を追加する</a></li></ol></li><li><a href="#toc6" tabindex="0">例: 外部SMSサービスと連携</a></li><li><a href="#toc7" tabindex="0">まとめ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">カスタムコンポーネントを作成する</span></h2>



<p>たとえば、独自の通知システムを作成するとします。以下の手順で実装できます。</p>



<h3 class="wp-block-heading"><span id="toc2">コンポーネントファイルを作成</span></h3>



<p><code>components</code> ディレクトリに <code>Notifier.php</code> を作成します。</p>



<pre class="wp-block-code"><code>namespace app\components;

use Yii;
use yii\base\Component;

class Notifier extends Component
{
    public $fromEmail = 'default@example.com'; // デフォルト値

    /**
     * 通知メールを送信する
     * @param string $toEmail
     * @param string $subject
     * @param string $message
     * @return bool
     */
    public function sendEmail($toEmail, $subject, $message)
    {
        return Yii::$app->mailer->compose()
            ->setFrom($this->fromEmail)
            ->setTo($toEmail)
            ->setSubject($subject)
            ->setTextBody($message)
            ->send();
    }

    /**
     * シンプルなログを記録
     * @param string $message
     */
    public function logNotification($message)
    {
        Yii::info($message, 'notifier');
    }
}</code></pre>



<h3 class="wp-block-heading"><span id="toc3">コンポーネントをアプリケーションに登録する</span></h3>



<p>アプリケーションの設定ファイル <code>config/web.php</code> に登録します。</p>



<pre class="wp-block-code"><code>'components' => &#91;
    'notifier' => &#91;
        'class' => 'app\components\Notifier',
        'fromEmail' => 'no-reply@yourapp.com', // プロパティを上書き
    ],
],</code></pre>



<h3 class="wp-block-heading"><span id="toc4">カスタムコンポーネントを使用する</span></h3>



<p>コントローラやサービスクラスで簡単に利用できます。</p>



<pre class="wp-block-code"><code>namespace app\controllers;

use Yii;
use yii\web\Controller;

class SiteController extends Controller
{
    public function actionSendNotification()
    {
        $notifier = Yii::$app->notifier;

        // 通知メールを送信
        $toEmail = 'user@example.com';
        $subject = 'お知らせ';
        $message = 'こんにちは、こちらは通知メールです！';

        if ($notifier->sendEmail($toEmail, $subject, $message)) {
            $notifier->logNotification("通知を $toEmail に送信しました。");
            return "通知メールを送信しました！";
        }

        return "通知メールの送信に失敗しました。";
    }
}</code></pre>



<h3 class="wp-block-heading"><span id="toc5">高度な設定を追加する</span></h3>



<p>場合によっては、外部サービスとの連携やさらなる機能拡張が必要になることがあります。その際、依存性を注入する方法が役立ちます。</p>



<h2 class="wp-block-heading"><span id="toc6">例: 外部SMSサービスと連携</span></h2>



<p><code>Notifier.php</code> を以下のように拡張します。</p>



<pre class="wp-block-code"><code>namespace app\components;

use Yii;
use yii\base\Component;

class Notifier extends Component
{
    public $smsService; // 外部サービスのインスタンス

    /**
     * SMSを送信する
     * @param string $phoneNumber
     * @param string $message
     * @return bool
     */
    public function sendSms($phoneNumber, $message)
    {
        if (!$this->smsService) {
            throw new \Exception("SMSサービスが設定されていません。");
        }

        return $this->smsService->send($phoneNumber, $message);
    }
}</code></pre>



<p>そして、設定ファイルでSMSサービスを注入します。</p>



<pre class="wp-block-preformatted">'components' => [<br>    'notifier' => [<br>        'class' => 'app\components\Notifier',<br>        'smsService' => [<br>            'class' => 'app\components\SmsService', // 外部サービスの実装クラス<br>        ],<br>    ],<br>],</pre>



<h2 class="wp-block-heading"><span id="toc7">まとめ</span></h2>



<p>Yii2のコンポーネントをカスタマイズすることで、再利用可能なコードを簡潔にまとめることができます。この記事で紹介した例を参考に、自分のプロジェクトに合わせたコンポーネントを設計してみてください。</p>



<p>ブログに掲載する際は、さらに適用例やスクリーンショットを追加して読みやすくすると良いでしょう！</p>





<a rel="noopener" href="https://www.yiiframework.com/doc/guide/2.0/ja/structure-application-components" title="アプリケーションの構造: アプリケーション・コンポーネント" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://www.yiiframework.com/image/facebook_cover.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">アプリケーションの構造: アプリケーション・コンポーネント</div><div class="blogcard-snippet external-blogcard-snippet"></div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.yiiframework.com/doc/guide/2.0/ja/structure-application-components" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">www.yiiframework.com</div></div></div></div></a>

]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/hrp7l4b680m2xzd557ywbcfrl5ki68i3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ユーザ認証の実装方法</title>
		<link>https://blog.takeho.com/smugmkxlxsf8by6zb8ifvem6rupeawe3/</link>
					<comments>https://blog.takeho.com/smugmkxlxsf8by6zb8ifvem6rupeawe3/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Sat, 03 Aug 2024 07:06:00 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[CRUD]]></category>
		<category><![CDATA[Gii]]></category>
		<category><![CDATA[Migration]]></category>
		<category><![CDATA[認証]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=143</guid>

					<description><![CDATA[Yii2のベーシックパックには標準でユーザ認証のサンプルがありますが、データベース管理ではなく簡易的な固定オブジェクトの為、商用利用に向かない仕様です。 ここではユーザ認証のサンプルを固定オブジェクトからデータベース管理 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Yii2のベーシックパックには標準でユーザ認証のサンプルがありますが、データベース管理ではなく簡易的な固定オブジェクトの為、商用利用に向かない仕様です。</p>



<p>ここではユーザ認証のサンプルを固定オブジェクトからデータベース管理に切り替える方法を説明します。</p>



<p>尚、Yii2のインストールがされていない場合は以下を参考してください。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-takeho wp-block-embed-takeho"><div class="wp-block-embed__wrapper">

<a href="https://blog.takeho.com/how-to-install-and-initialize-yii2/" title="Yii2のインストール・初期設定方法" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://blog.takeho.com/wp-content/uploads/2024/07/20240718.webp" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">Yii2のインストール・初期設定方法</div><div class="blogcard-snippet external-blogcard-snippet">日本国では人気の無いフレームワークYii2 充実したライブラリと機能性の高さの割に大規模なウェブアプリケーションだけでなく小規模なウェブアプリケーションでも開発しやすいようディレクトリの構成変更が簡単にできる便利なフレームワークです。 この</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://blog.takeho.com/y96x9r38o0zq6jvjcvs3znskqu59mymz/" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">blog.takeho.com</div></div></div></div></a>
</div></figure>



<h2 class="wp-block-heading">データベーステーブルとモデルの作成</h2>



<p>マイグレーションを使用してユーザ管理用データベーステーブルを用意します。</p>



<h3 class="wp-block-heading">データベーステーブルの作成</h3>



<h4 class="wp-block-heading">マイグレーションファイルの作成</h4>



<p>次のコマンドを実行してマイグレーションファイルを作成します。</p>



<pre class="wp-block-code"><code># php yii migrate/create create_user_table --fields="username:string(32):notNull:unique,password:string(64):notNull,access_token:string(32),auth_key:string(32)"
Yii Migration Tool (based on Yii v2.0.51)

Create new migration '/var/www/html/yii2.takeho.com/migrations/m240806_073739_create_user_table.php'? (yes|no) &#91;no]:yes
New migration created successfully.
#</code></pre>



<p>コマンド実行後、migrationsのディレクトリの作成及びその中に以下のファイルが生成されます。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td>生成ファイル名</td><td>m000000_000000_create_user_table.php</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>&lt;?php

use yii\db\Migration;

/**
 * Handles the creation of table `{{%user}}`.
 */
class m000000_000000_create_user_table extends Migration
{
    /**
     * {@inheritdoc}
     */
    public function safeUp()
    {
        $this-&gt;createTable('{{%user}}', &#91;
            'id' =&gt; $this-&gt;primaryKey(),
            'username' =&gt; $this-&gt;string(32)-&gt;notNull()-&gt;unique(),
            'password' =&gt; $this-&gt;string(64)-&gt;notNull(),
            'access_token' =&gt; $this-&gt;string(32),
            'api_key' =&gt; $this-&gt;string(32),
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function safeDown()
    {
        $this-&gt;dropTable('{{%user}}');
    }
}</code></pre>



<h4 class="wp-block-heading">マイグレーションの反映</h4>



<p>次の要領でコマンドを実行します。</p>



<pre class="wp-block-code"><code># php yii migrate
Yii Migration Tool (based on Yii v2.0.51)

Creating migration history table "migration"...Done.
Total 1 new migration to be applied:
        m240806_073739_create_user_table

Apply the above migration? (yes|no) &#91;no]:yes
*** applying m240806_073739_create_user_table
    &gt; create table {{%user}} ... done (time: 0.006s)
*** applied m240806_073739_create_user_table (time: 0.012s)


1 migration was applied.

Migrated up successfully.
#</code></pre>



<p>上記実行後、データベースにuserテーブルが作成されている事が確認できます。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="878" height="264" src="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_01_2.png" alt="" class="wp-image-135" srcset="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_01_2.png 878w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_01_2-640x192.png 640w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_01_2-768x231.png 768w" sizes="(max-width: 878px) 100vw, 878px" /></figure>



<h3 class="wp-block-heading">モデルの作成</h3>



<p>モデルの作成にはYii2のGUI生成ツール<strong>Gii</strong>を仕様します。</p>



<h4 class="wp-block-heading">モデル生成ページへアクセス</h4>



<p>次のURLへアクセスします。</p>



<pre class="wp-block-code"><code>http:&#47;&#47;www.example.com/index.php?r=gii</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1092" height="781" src="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_01.png" alt="" class="wp-image-142" srcset="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_01.png 1092w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_01-640x458.png 640w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_01-768x549.png 768w" sizes="(max-width: 1092px) 100vw, 1092px" /></figure>



<p>Model Generatorの項目にある<strong>Start</strong>を押下します。</p>



<h4 class="wp-block-heading">パラメータ設定</h4>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1096" height="1256" src="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_02.png" alt="" class="wp-image-136" srcset="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_02.png 1096w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_02-558x640.png 558w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_02-768x880.png 768w" sizes="(max-width: 1096px) 100vw, 1096px" /></figure>



<p>上記を参考に以下の情報を入力・設定し、<strong>Preview</strong>を押下します。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td>Use Table Prefix</td><td>－</td></tr><tr><td>Use Schema Name</td><td>チェック</td></tr><tr><td>Table Name</td><td>user</td></tr><tr><td>Standardize Capitals</td><td>－</td></tr><tr><td>Singularize</td><td>－</td></tr><tr><td>Model Class Name</td><td>User</td></tr><tr><td>Generate Relations From Current Schema</td><td>チェック</td></tr><tr><td>Use &#8216;::class&#8217;</td><td>チェック</td></tr><tr><td>Generate Labels From DB Comments</td><td>チェック</td></tr><tr><td>Generate ActiveQuery</td><td>－</td></tr><tr><td>Enable I18N</td><td>－</td></tr></tbody></table></figure>



<h4 class="wp-block-heading">確認画面（プレビュー）</h4>



<p><strong>Generate</strong>を押下します。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1201" height="596" src="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_03.png" alt="" class="wp-image-137" srcset="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_03.png 1201w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_03-640x318.png 640w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_03-768x381.png 768w" sizes="(max-width: 1201px) 100vw, 1201px" /></figure>



<h4 class="wp-block-heading">生成確認</h4>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="1200" height="603" src="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_04.png" alt="" class="wp-image-140" style="width:840px;height:auto" srcset="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_04.png 1200w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_04-640x322.png 640w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_04-768x386.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /></figure>



<p>次のファイルが生成されているか確認します。</p>



<pre class="wp-block-code"><code>/models/User.php</code></pre>



<h2 class="wp-block-heading">CRUD（create、read、update、delete）機能の追加とデータの投入</h2>



<p>モデルと同じ要領でGiiで以下のパラメータを指定してCURDを生成します。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td>Model Class</td><td>User</td></tr><tr><td>Search Model Class</td><td>app\models\UserSearch</td></tr><tr><td>Controller Class</td><td>app\controllers\UserController</td></tr><tr><td>View Path</td><td>@app\views\user</td></tr><tr><td>Enable I18N</td><td>－</td></tr><tr><td>Enable Pjax</td><td>チェック</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">動作確認</h3>



<p>次のURLへアクセスしてCRUDが機能するか確認します。</p>



<pre class="wp-block-code"><code>http:&#47;&#47;www.example.com?r=user/index</code></pre>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="1217" height="518" src="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_07.png" alt="" class="wp-image-155" style="width:840px;height:auto" srcset="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_07.png 1217w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_07-640x272.png 640w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_07-768x327.png 768w" sizes="(max-width: 1217px) 100vw, 1217px" /></figure>



<h3 class="wp-block-heading">User登録フォームの改修</h3>



<p>前頁で作成したUserの<strong>CURD</strong>には次の問題があるので修正を行います。</p>



<ul class="wp-block-list">
<li>Auth Keyの入力は不要だか新規登録時に自動で値が設定される必要がある</li>



<li>Access Tokenの入力が不要</li>



<li>パスワードが平文保存されている</li>
</ul>



<h4 class="wp-block-heading">Auth Keyの値を自動設定する</h4>



<p>次のコードを参考にmodel/User.phpへbeforeSaveメソッドを追加します。</p>



<pre class="wp-block-code"><code>  public function beforeSave($insert)
  {
      if (parent::beforeSave($insert)) {
          if ($this-&gt;isNewRecord) {
              $this-&gt;auth_key = \Yii::$app-&gt;security-&gt;generateRandomString();
          }
          return true;
      }
      return false;
  }</code></pre>



<p>上記より保存する前に新しいレコードの追加（insert）が確認の上、ランダムな文字列をauth_keyへセットします。</p>



<h4 class="wp-block-heading">Auth KeyとAccess Token<strong>の</strong>入力を消す</h4>



<p><strong>Auth Key</strong>と<strong>Access Token</strong>は動的に生成する情報になり入力するべき項目ではありませんので、入力項目を消します。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td>ファイル名</td><td>/views/user/_form.php</td></tr></tbody></table></figure>



<p>次の項目を削除します。</p>



<pre class="wp-block-code"><code>    &lt;?= $form-&gt;field($model, 'access_token')-&gt;textInput(&#91;'maxlength' =&gt; true]) ?&gt;

    &lt;?= $form-&gt;field($model, 'auth_key')-&gt;textInput(&#91;'maxlength' =&gt; true]) ?&gt;</code></pre>



<h4 class="wp-block-heading">パスワードの保存をハッシュ値に変更</h4>



<p>次のコードを参考にmodel/User.phpのbeforeSaveメソッドを編集します。</p>



<pre class="wp-block-code"><code>    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            $this-&gt;password = Yii::$app-&gt;security-&gt;generatePasswordHash($this-&gt;password);
            if ($this-&gt;isNewRecord) {
                $this-&gt;auth_key = Yii::$app-&gt;security-&gt;generateRandomString();
            }
            return true;
        }
        return false;
    }</code></pre>



<p>上記のように<strong>$this-&gt;password</strong>の値をセキュリティクラスからハッシュ値を求めた値に設定します。</p>



<h2 class="wp-block-heading">認証インターフェイスの環境を整える</h2>



<p>認証インターフェイスの利用に必須となる次のメソッドをUserモデルに追加します。</p>



<pre class="wp-block-code"><code>
    public static function findIdentity($id)
    {
      return static::findOne($id);
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
      return static::findOne(&#91;'access_token' => $token]);
    }

    public static function findByUsername($username)
    {
      return static::findOne(&#91;'username' => $username]);
    }

    public function getId()
    {
      return $this->id;
    }

    public function getAuthKey()
    {
      return $this->auth_key;
    }

    public function validateAuthKey($authKey)
    {
      return $this->getAuthKey() === $authKey;
    }

    public function validatePassword($password)
    {
      return Yii::$app->getSecurity()->validatePassword($password, $this->password);
    }</code></pre>



<h2 class="wp-block-heading">アクセス確認</h2>



<p>次のURLへアクセスして認証確認を行います。</p>



<pre class="wp-block-code"><code>http:&#47;&#47;www.example.com/index.php?r=site/login</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1105" height="699" src="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_09.png" alt="" class="wp-image-165" srcset="https://blog.takeho.com/wp-content/uploads/2024/08/20240803_09.png 1105w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_09-640x405.png 640w, https://blog.takeho.com/wp-content/uploads/2024/08/20240803_09-768x486.png 768w" sizes="(max-width: 1105px) 100vw, 1105px" /></figure>



<p>ログインに成功したらデバックツールバーの<strong>User</strong>を押下して認証されている情報を確認できます。</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/smugmkxlxsf8by6zb8ifvem6rupeawe3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Yii2のインストール・初期設定方法</title>
		<link>https://blog.takeho.com/y96x9r38o0zq6jvjcvs3znskqu59mymz/</link>
					<comments>https://blog.takeho.com/y96x9r38o0zq6jvjcvs3znskqu59mymz/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Thu, 18 Jul 2024 05:49:55 +0000</pubDate>
				<category><![CDATA[Yii2]]></category>
		<category><![CDATA[Composer]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=47</guid>

					<description><![CDATA[日本国では人気の無いフレームワークYii2 充実したライブラリと機能性の高さの割に大規模なウェブアプリケーションだけでなく小規模なウェブアプリケーションでも開発しやすいようディレクトリの構成変更が簡単にできる便利なフレー [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>日本国では人気の無いフレームワークYii2</p>



<p>充実したライブラリと機能性の高さの割に大規模なウェブアプリケーションだけでなく小規模なウェブアプリケーションでも開発しやすいようディレクトリの構成変更が簡単にできる便利なフレームワークです。</p>



<p>この記事ではYii2のインストールと開発開始までの初期設定方法を説明します。</p>



<h3 class="wp-block-heading"><span id="toc1">Yii2のインストール</span></h3>



<p>次のcomposerコマンドでYii2をインストールします</p>



<pre class="wp-block-code"><code># cd ＜インストールするディレクトリ＞
# composer create-project --prefer-dist yiisoft/yii2-app-basic ＜プロジェクト名＞</code></pre>



<h3 class="wp-block-heading"><span id="toc2">コード生成ツールGiiの許可設定</span></h3>



<p>Yii2にはGUI上で次のファイルを自動生成する機能があります。</p>



<ul class="wp-block-list">
<li><strong>Model Generator</strong><br>このジェネレータは、指定されたデータベーステーブルのActiveRecordクラスを生成します。</li>



<li><strong>CRUD Generator</strong><br>このジェネレータは、指定されたデータモデルのCRUD(作成、読み取り、更新、削除)操作を実装するコントローラとビューを生成します。</li>



<li><strong>Controller Generator</strong><br>このジェネレータは、1つまたは複数のコントローラアクションと対応するビューを持つ新しいコントローラクラスをすばやく生成するのに役立ちます。</li>



<li><strong>Form Generator</strong><br>このジェネレータは、指定されたモデルクラスの入力を収集するフォームを表示するビュースクリプトファイルを生成します。</li>



<li><strong>Module Generator</strong><br>このジェネレータは、Yiiモジュールに必要なスケルトンコードを生成するのに役立ちます。</li>



<li><strong>Extension Generator</strong><br>このジェネレータは、Yii拡張に必要なファイルを生成するのに役立ちます。</li>
</ul>



<p>Giiの使用は開発環境でのみ利用できるようIP制限を掛けて特定のアクセス元IPのみ許可する必要があります。</p>



<pre class="wp-block-code"><code>/config/web.php

    $config&#91;'bootstrap']&#91;] = 'gii';
    $config&#91;'modules']&#91;'gii'] = &#91;
        'class' => 'yii\gii\Module',
        // uncomment the following to add your IP if you are not connecting from localhost.
        'allowedIPs' => &#91;'127.0.0.1', '::1'], // ⇦コメントアウトを外しアクセス元IPを設定
    ];</code></pre>



<div class="wp-block-cocoon-blocks-tab-caption-box-1 tab-caption-box block-box not-nested-style cocoon-block-tab-caption-box"><div class="tab-caption-box-label block-box-label box-label"><span class="tab-caption-box-label-text block-box-label-text box-label-text">注意</span></div><div class="tab-caption-box-content block-box-content box-content">
<p>Giiでのコード生成はローカルでの開発環境を前提としています。</p>



<p>別途外部サーバ等でGiiを使用する場合、コード生成先ディレクトリの権限の影響によりファイル生成が失敗しますのでご注意ください。</p>
</div></div>



<h3 class="wp-block-heading"><span id="toc3">デバックツールバーの許可設定</span></h3>



<p>デバックツールバーもGiiと同様にアクセス元IPの許可設定をします。</p>



<pre class="wp-block-code"><code>/config/web.php

    $config&#91;'bootstrap']&#91;] = 'debug';
    $config&#91;'modules']&#91;'debug'] = &#91;
        'class' => 'yii\debug\Module',
        // uncomment the following to add your IP if you are not connecting from localhost.
        'allowedIPs' => &#91;'127.0.0.1', '::1'], // ⇦コメントアウトを外しアクセス元IPを設定
    ];</code></pre>



<h3 class="wp-block-heading"><span id="toc4">データベース接続設定</span></h3>



<p>データベースの接続設定をします。</p>



<pre class="wp-block-code"><code>config/db.php

return &#91;
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=＜データベース名＞',
    'username' => '＜ユーザ名＞',
    'password' => '＜パスワード＞',
    'charset' => 'utf8',</code></pre>



<p>以上で完了です。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/y96x9r38o0zq6jvjcvs3znskqu59mymz/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
