カテゴリー
Laravel

【Laravel】Breeze + React + TypeScriptインストール方法

はじめに

LaravelはPHPフレームワークの中でも人気が高く、フロントエンドとの連携が簡単に行えます。本記事では、Laravel 11にBreezeを導入し、ReactとTypeScriptを使ったモダンな開発環境をローカルで構築する手順を紹介します。


必要なツールと環境

事前に以下のツールをインストールしておきましょう。

  • PHP (バージョン8.1以上)
  • Composer
  • Node.js (LTS推奨)
  • npm または Yarn
  • データベース (例: MySQL)

また、Laravelの開発環境としてLaravel Sailを利用することもおすすめです。


環境構築手順

Laravel 11 プロジェクトの作成

まず、Composerを使って新しいLaravel 11プロジェクトを作成します。

Bash
composer create-project laravel/laravel laravel-react-ts
Bash
cd laravel-react-ts

Breezeのインストールと設定

Laravel Breezeは、認証を簡単にセットアップできる軽量なスターターパックです。

Bash
composer require laravel/breeze --dev

インストールが完了したら、BreezeをReactとTypeScriptオプション付きでセットアップします。

Bash
php artisan breeze:install react --typescript

npmパッケージのインストールとビルド

以下のコマンドを実行して、必要なnpmパッケージをインストールします。

Bash
npm install

コマンドを実行することで、フロントエンドの開発サーバーが起動します。

Bash
npm run dev

Laravel Debugbar追加

Bash
composer require --dev barryvdh/laravel-debugbar

設定ファイルの公開

Bash
php artisan vendor:publish --provider="Barryvdh\Debugbar\ServiceProvider"

データベースの設定

.envファイルを編集して、データベースの接続情報を設定します。

Bash
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel_db DB_USERNAME=root
DB_PASSWORD=your_password

設定を反映するために、以下のコマンドを実行してデータベースをマイグレーションします。

Bash
php artisan migrate

ローカル開発サーバーの起動

以下のコマンドでLaravelの開発サーバーを起動します。

Bash
php artisan serve

ブラウザでhttp://localhost:8000を開き、Laravelのトップページが表示されることを確認します。


Breeze + React + TypeScriptの動作確認

Breezeの初期セットアップにより、ログイン・登録画面がReactとTypeScriptで構築されています。これらの画面が正しく動作しているか確認しましょう。


よくある問題と解決策

npmパッケージのインストール時にエラーが発生する

依存関係の不整合が原因の場合があります。以下のコマンドで解決できる場合があります。

Bash
npm install --legacy-peer-deps

おわりに

この記事では、Laravel 11、Breeze、React、TypeScriptを使ったモダンな開発環境を構築する手順を紹介しました。この環境を基に、さらなるカスタマイズやプロジェクトの開発を楽しんでください!

カテゴリー
Laravel

【Laravel】+Reactインストール方法:mac

はじめに

Laravelは、PHPの中でも便利なWebフレームワークの一つです。そしてReactは、モダンなUIの構築に便利なJavaScriptライブラリです。この記事では、Laravel 11とReactをインストールし、認証機能も含めたアプリの構築手順を解説します。デザイン系パッケージを使用するアプローチも追加しています。


システムの前提条件

  • macOS
  • PHP 8.2+ (バージョンにより違う可能性があります)
  • Composer
  • Node.js (最新バージョン)
  • NPMまたはYarn

Laravelの新規プロジェクト作成

Laravelのプロジェクトを作成します。

Bash
composer create-project laravel/laravel laravel-react "^11.0"

既存のディレクトリに作成する場合、gitlabなどからクローン後などはクローン後などは一度空にしてから行う

Bash
composer create-project laravel/laravel . "^11.0"

プロジェクトディレクトリに移動します。

Bash
cd laravel-react

Laravelをローカルサーバーで起動して、正常に動作しているか確認します。

Bash
php artisan serve

ブラウザでhttp://127.0.0.1:8000を開き、Laravelのデフォルトページが表示されれば成功です。

Laravel Debugbar追加

Bash
composer require --dev barryvdh/laravel-debugbar

設定ファイルの公開

Bash
php artisan vendor:publish --provider="Barryvdh\Debugbar\ServiceProvider"

Reactのインストール

Reactをインストールします。

Bash
composer require laravel/ui
php artisan ui react
npm install
npm run dev

この段階でReactのフロントエンドツールが構築され、resources/jsにReactのファイルが追加されます。

React Developer Toolsの追加

React Developer Toolsは、Reactアプリケーションのデバッグを支援するChrome拡張機能です。以下のリンクからインストールできます。

インストール後、Chromeのデベロッパーツールに「Components」や「Profiler」タブが追加され、Reactコンポーネントの構造や状態を視覚的に確認できます。

React Developer Toolsリンク


Breezeによる認証機能の構築

LaravelのBreezeパッケージを使用すると、認証機能を快速に構築できます。

Breezeのインストール

Bash
composer require laravel/breeze --dev
php artisan breeze:install react
npm install
npm run dev

.envを編集しMySQLを設定する:MySQLの起動が必要

rootやパスワードを変更の際は、MySQLから作成する必要がある。

Bash
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=local_XXXX
DB_USERNAME=root
DB_PASSWORD=

DBなど作成する

Bash
php artisan migrate

ブラウザで認証ページを確認します。

http://127.0.0.1:8000/register

http://127.0.0.1:8000/login

認証関連の画面が正常に表示されれば完了です。

デザイン系パッケージの追加

最近のUIフレームワークを利用すると、デザイン構築が楽になります。下記はTailwind CSSを使用する例です。

Tailwind CSSのインストールinit

Bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init

tailwind.config.jsに構成を追加:既にある場合は作業不要

JavaScript
module.exports = {
    content: [
        './resources/**/*.blade.php',
        './resources/**/*.js',
        './resources/**/*.vue',
    ],
    theme: {
        extend: {},
    },
    plugins: [],
}

Tailwind CSSをresources/css/app.cssで有効化:既にある場合は作業不要

@tailwindディレクティブを追加します。

CSS
@tailwind base;
@tailwind components;
@tailwind utilities;

CSSをビルド

Bash
npm run dev

Tailwind CSSが適用されることを確認LaravelのBladeテンプレート内でTailwindのクラスを使用して、デザインが適用されるか確認します。


開発の次のステップ

  • コンポーネントの分割: Reactコンポーネントを分割して再利用性を高める。
  • APIとの連携: LaravelのAPIとReactを連携して動的な機能を実装。
  • テスト: LaravelのPHPUnitとReactのJestを活用してテスト環境を整える。
  • デプロイ: 本番環境にデプロイし、パフォーマンスを最適化。

これでLaravel 11とReactを組み合わせたアプリケーションの基本的なセットアップが完了です! Tailwind CSSを使用してデザインも強化されたため、次のステップとしてアプリケーションの機能拡張を進めてみてください。

カテゴリー
Laravel

【Laravel】認証機能の追加方法

Laravelは、認証機能を迅速に実装できる強力な機能を提供しています。本記事では、Laravel 11を使用して、CoreUIデザインテンプレートで認証機能を実装する方法を解説します。

Laravel 11のインストール

まずはLaravel 11をインストールします。以下のコマンドで新しいLaravelプロジェクトを作成します。

Bash
composer create-project --prefer-dist laravel/laravel laravel-auth-example

インストールが完了したら、プロジェクトディレクトリに移動します。

Bash
cd laravel-auth-example

CoreUIテンプレートのインストール

CoreUIは、管理画面向けのレスポンシブでモダンなデザインテンプレートです。CoreUIを使用するために、まずnpmを使って依存関係をインストールします。

Bash
npm install @coreui/coreui

次に、resources/js/app.jsにCoreUIのスタイルとスクリプトをインポートします。

JavaScript
import { createApp } from 'vue'
import CoreUI from '@coreui/coreui';
import App from './App.vue';

CoreUIのスタイルシートも追加します。

JavaScript
import '@coreui/coreui/dist/css/coreui.min.css';

Laravelの認証機能をセットアップ

Laravel 11では、artisanコマンドを使用して簡単に認証機能を設定できます。以下のコマンドで認証機能をインストールします。

JavaScript
composer require laravel/ui php artisan ui vue --auth npm install npm run dev

これで、基本的な認証機能(ログイン、登録、パスワードリセット機能)がインストールされます。

CoreUIスタイルに合わせたカスタマイズ

次に、認証ビューをCoreUIに合わせてカスタマイズします。resources/views/authディレクトリ内のファイル(login.blade.phpregister.blade.php など)を開き、CoreUIのコンポーネントを使用してデザインを調整します。

例えば、ログインフォームのデザインを次のように変更します。

HTML
<div class="c-card">
    <div class="c-card-header">
        <h4 class="card-title">ログイン</h4>
    </div>
    <div class="c-card-body">
        <form method="POST" action="{{ route('login') }}">
            @csrf
            <div class="form-group">
                <label for="email">メールアドレス</label>
                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autofocus>
                @error('email')
                    <span class="invalid-feedback" role="alert">
                        <strong>{{ $message }}</strong>
                    </span>
                @enderror
            </div>
            <div class="form-group">
                <label for="password">パスワード</label>
                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required>
                @error('password')
                    <span class="invalid-feedback" role="alert">
                        <strong>{{ $message }}</strong>
                    </span>
                @enderror
            </div>
            <button type="submit" class="btn btn-primary btn-block">ログイン</button>
        </form>
    </div>
</div>

認証後のリダイレクト設定

認証が成功した後、ユーザーをどのページにリダイレクトするかを設定するには、app/Http/Controllers/Auth/LoginController.phpredirectToプロパティを設定します。

PHP
protected $redirectTo = '/dashboard';

これで、ログイン後にユーザーがダッシュボードページにリダイレクトされるようになります。

CoreUIダッシュボードの作成

次に、ログイン後に表示されるダッシュボードページを作成します。resources/views/dashboard.blade.phpを作成し、CoreUIのコンポーネントを使用して管理画面をデザインします。

HTML
<div class="c-dashboard">
    <h1>ダッシュボード</h1>
    <p>ようこそ、{{ Auth::user()->name }} さん!</p>
</div>

ユーザーの作成

usersテーブルのデータを作成する

Bash
php artisan make:seeder UsersTableSeeder 

シーダーファイルサンプル

database/seeders/UsersTableSeeder.php

PHP
use Illuminate\Database\Seeder;
use App\Models\User;

class UsersTableSeeder extends Seeder
{
    public function run()
    {
        // 管理者ユーザーを作成
        User::create([
            'name' => 'Admin User',
            'email' => 'admin@example.com',
            'password' => bcrypt('password123'), // パスワードは必ずハッシュ化
        ]);

        // 一般ユーザーを複数作成
        User::factory()->count(10)->create(); // Factoryが利用可能な場合
    }
}

DatabaseSeeder に登録

PHP
public function run()
{
    $this->call([
        UsersTableSeeder::class,
    ]);
}

シーディングを実行

Bash
php artisan db:seed

認証機能の確認

http://127.0.0.1:8000/loginへアクセス

認証機能Breezeのログイン画面
認証機能Breezeのログイン画面

ログイン後の画面

認証機能Breezeのダッシュボード

セキュリティ強化の設定

Laravelはデフォルトでセキュリティが強化されていますが、必要に応じて、config/auth.php.envファイルで詳細な設定を行うことができます。特に、パスワードのハッシュアルゴリズムやセッションの設定などを確認しておきましょう。


結論

Laravel 11とCoreUIを使用することで、迅速に美しい認証機能を実装できます。基本的なセットアップが完了した後は、デザインやユーザー体験をカスタマイズして、自分のプロジェクトに最適な認証機能を作り上げていきましょう。

カテゴリー
Laravel

【Laravel】無料デザインテンプレート

Laravelは、使いやすいフレームワークとして多くの開発者に支持されています。しかし、デザイン面で魅力的なテンプレートを無料で探すのは意外と手間がかかるものです。この記事では、無料で使えるおすすめのLaravelデザインテンプレートをいくつかご紹介します。また、これらを使って数名のユーザーがログインし、データを更新し、APIでWordPressと連携する方法についても解説します。

無料のLaravelデザインテンプレートの特徴

無料で提供されているLaravelテンプレートの中には、以下のような特徴を持つものが多いです。

  • レスポンシブデザイン対応
  • シンプルかつモダンなUI
  • カスタマイズが容易
  • 一般的な認証システムの統合済み

以下に具体例を挙げていきます。

おすすめLaravelデザインテンプレート

AdminLTE

AdminLTEは、Laravelで使える無料の管理画面テンプレートとして非常に人気があります。Bootstrapをベースにしており、管理者用ダッシュボードや統計情報の表示に最適です。

  • 特徴:カスタマイズ性が高い、多彩なUIコンポーネント
  • ダウンロード:公式サイト

CoreUI

CoreUIは、軽量で使いやすいLaravel用の無料テンプレートです。基本的な管理画面を素早く構築でき、API連携にも適しています。

  • 特徴:多言語対応、グラフやチャート機能
  • ダウンロード:公式サイト

Material Dashboard Laravel

Material DashboardはGoogleのMaterial Designを基に作られたテンプレートです。視覚的に洗練されており、ユーザーエクスペリエンスを向上させます。

  • 特徴:カラフルで視覚的に魅力的なデザイン
  • ダウンロード:公式サイト

ユーザーがログインしデータを更新する仕組み

Laravelを使うことで、数名のユーザーがログインしてデータを更新する機能を簡単に構築できます。以下のステップで進めることができます。

認証機能の実装

Laravelの認証機能はphp artisan make:authコマンド(Laravel 8以降ではlaravel/uiパッケージを使用)を実行するだけでセットアップできます。

データ更新機能の構築

  • ルーティングroutes/web.phpでルートを設定します。
  • コントローラーphp artisan make:controllerコマンドでコントローラーを作成し、データ更新ロジックを記述します。
  • ビュー:Bladeテンプレートを使用して、データ入力フォームを作成します。

APIでWordPressとデータ連携

LaravelからWordPressにデータを連携するためには、REST APIを利用します。以下はその流れです。

WordPress REST APIの設定

WordPressには標準でREST APIが組み込まれています。/wp-json/wp/v2/postsエンドポイントを使用して投稿データを更新できます。

LaravelからAPIを呼び出す

LaravelではGuzzleHTTPHttpファサードを使用してAPIを呼び出せます。

トークン認証の設定

WordPressのAPIを利用するには、認証が必要です。JWT Authentication for WP REST APIプラグインを導入し、適切なアクセストークンを発行します。

まとめ

Laravelの無料デザインテンプレートを活用することで、迅速に美しいアプリケーションを開発できます。また、ログイン機能やデータ更新機能を組み込み、APIでWordPressと連携することで、高度な機能を持つアプリケーションを実現できます。ぜひ、この記事を参考にして開発を進めてみてください。

カテゴリー
Laravel

【Laravel】インストール方法:mac

[temp id=3]

Laravelは、モダンなWebアプリケーションを開発するためのPHPフレームワークです。この記事では、MacにLaravelをインストールし、簡単な開発環境を構築する方法を解説します。

Laravel var11


Laravelインストールの前提条件

Laravelをインストールするためには、以下のソフトウェアが必要です。

必要なソフトウェア

  1. Homebrew(Mac用のパッケージマネージャ)
  2. PHP(バージョン8.x以上を推奨)
  3. Composer(PHPの依存管理ツール)
  4. Node.js(フロントエンドアセットの管理用)

必要なソフトウェアのインストール

1 Homebrewのインストール

Homebrewを使うと、Macに必要なソフトウェアを簡単にインストールできます。ターミナルを開き、以下のコマンドを実行してください。

Bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

インストールが終わったら、brew コマンドが正しく動作するか確認します。

Bash
brew --version

PHPのインストール

Homebrewを使ってPHPをインストールします。

Bash
brew install php

インストール後、以下のコマンドでPHPのバージョンを確認します。

Bash
php -v

Composerのインストール

次に、Composerをインストールします。

Bash
brew install composer

インストール後、以下のコマンドでComposerのバージョンを確認します。

Bash
composer --version

Node.jsのインストール

Laravelのフロントエンドアセットを管理するために、Node.jsをインストールします。

Bash
brew install node

インストール後、以下のコマンドでNode.jsとnpmのバージョンを確認します。

Bash
node -v npm -v

Laravelプロジェクトの作成

新しいLaravelプロジェクトの作成

以下のコマンドを実行して、Laravelプロジェクトを作成します。

Bash
composer create-project --prefer-dist laravel/laravel my-project

これにより、my-project という名前のLaravelプロジェクトが作成されます。

プロジェクトフォルダに移動

作成したプロジェクトのフォルダに移動します。

Bash
cd my-project

開発サーバの起動

以下のコマンドでLaravelの開発サーバを起動します。

Bash
php artisan serve

起動が成功すると、次のようなメッセージが表示されます。

Bash
Starting Laravel development server: http://127.0.0.1:8000

ブラウザで http://127.0.0.1:8000 にアクセスすると、Laravelのウェルカムページが表示されます。


フロントエンドアセットのセットアップ

Laravelのフロントエンドアセットを利用するには、Node.jsを使って依存関係をインストールする必要があります。

依存関係のインストール

以下のコマンドを実行して、node_modules をインストールします。

Bash
npm install

開発用アセットのビルド

以下のコマンドでフロントエンドアセットをビルドします。

Bash
npm run dev

これにより、Laravelのフロントエンドアセットが開発環境で使用できるようになります。

まとめ

これで、MacにLaravelをインストールし、開発環境を構築する手順が完了しました。以下の手順を実行すれば、いつでもプロジェクトを再開できます。

  1. プロジェクトディレクトリに移動:cd my-project
  2. 開発サーバを起動:php artisan serve

Laravelを使えば、簡単にモダンなWebアプリケーションを開発できます。ぜひ、今回の手順を参考にして、Laravelでの開発を楽しんでください!

カテゴリー
Laravel

【Laravel】よく使うコマンド

[temp id=3]

Laravelを開発していると、Artisanコマンドをよく使用します。Artisanコマンドは、データベースの操作やサーバーの起動、キャッシュのクリアなど、さまざまな作業を効率よく行うためのツールです。この記事では、Laravel開発中に使用頻度の高いArtisanコマンドを紹介します。

サーバーを起動する

Bash
php artisan serve

ローカル開発サーバーを起動します。デフォルトでは http://127.0.0.1:8000 でアクセスできます。

マイグレーション関連

マイグレーションの実行

Bash
php artisan migrate

データベースのマイグレーションを実行します。

マイグレーションをリセット

Bash
php artisan migrate:reset

すべてのマイグレーションをリセットします。

マイグレーションのロールバック

Bash
artisan migrate:rollback

最後に実行されたマイグレーションをロールバックします。

マイグレーションのリフレッシュ

Bash
php artisan migrate:refresh

マイグレーションをリセットし、再度実行します。

新しいマイグレーションファイルを作成

Bash
php artisan make:migration create_table_name

モデルの作成

Bash
php artisan make:model ModelName

新しいモデルを作成します。--migration オプションを使うと、マイグレーションファイルも同時に作成できます。

コントローラーの作成

Bash
php artisan make:controller ControllerName

新しいコントローラーを作成します。リソースコントローラーを作成するには、--resource オプションを使用します。

シーダーファイル作成

Bash
php artisan make:seeder UsersTableSeeder

シーダー(データのダミーデータ生成)

Bash
php artisan db:seed

シーダーを実行して、データベースにダミーデータを挿入します。

  • 特定のシーダーのみ実行
Bash
php artisan db:seed --class=SeederClassName

ファクトリー(モデルのダミーデータ生成)

Bash
php artisan tinker

TinkerはREPL(対話型シェル)で、Eloquentモデルをインタラクティブに操作できます。例えば、モデルのインスタンスを作成してデータベースに保存することができます。

  • モデルをファクトリで作成phpコードをコピーする\App\Models\User::factory()->create();

キャッシュ関連

キャッシュをクリア

Bash
php artisan cache:clear

コンフィグキャッシュのクリア

Bash
php artisan config:cache

ルートキャッシュのクリア

Bash
php artisan route:clear

ビューキャッシュのクリア

Bash
php artisan view:clear

Artisanコマンドのヘルプ

Bash
php artisan list

使用可能なすべてのコマンドをリスト表示します。

ログの確認(ログをtailする)

Bash
tail -f storage/logs/laravel.log

Laravelのログファイル(storage/logs/laravel.log)の内容をリアルタイムで確認します。

バッチ処理(キューの処理)

Bash
php artisan queue:work

キューに格納されたジョブを処理します。バックグラウンドで非同期処理を行いたい場合に便利です。

Artisianコマンドの作成

Bash
php artisan make:command CommandName

自分専用のArtisanコマンドを作成できます。

イベントとリスナー

イベントの作成

Bash
php artisan make:event EventName

リスナーの作成

Bash
php artisan make:listener ListenerName --event=EventName

テストの実行

Bash
php artisan test

Laravelのテストを実行します。

特定のテストを実行

Bash
php artisan test --filter TestClassName

ジョブの作成

Bash
php artisan make:job JobName

新しいジョブクラスを作成します。キュー処理に使う場合などに便利です。

キャッシュの前処理(コンフィグやルートのキャッシュ生成)

Bash
php artisan optimize

Laravelアプリケーションを最適化して、パフォーマンスを向上させます。主に本番環境での使用を想定しています。

16. 環境設定ファイルの確認

Bash
php artisan env

現在の環境設定を確認できます。


これらのコマンドは、Laravelの開発において非常に役立つものであり、特に開発中に頻繁に使用するものです。覚えておくと、作業の効率が大幅に向上します。

カテゴリー
EC-CUBE Git

【Git】リリース作業

こんにちは!

現在EC-CUBE4のカスタマイズ案件やっている、@vVv_kenshi_vVvです!

developブランチのリリースを例に紹介します。

シンプルなリリース方法

projectディレクトリへ移動

ShellScript
cd prohject

作業開始時間の確認

ShellScript
date +"%Y-%m-%d %H:%M:%S"

現在ブランチの確認

ShellScript
git branch

gitの状態確認

ShellScript
git status

リモートから差分取得+削除済みブランチも同期

ShellScript
git fetch --prune

リモートから差分取得+削除済みブランチも同期

ShellScript
git fetch --prune

現在のチェックアウトとリモートの差分確認

ShellScript
git log --oneline --no-merges HEAD..origin/develop

リモートから取得してきた最新のコミットをマージ

ShellScript
git merge origin/develop

しっかり再度マージされたか確認

ShellScript
git log --oneline --no-merges HEAD..origin/develop

作業終了時間の確認

ShellScript
date +"%Y-%m-%d %H:%M:%S"

ECCUBE4のリリース方法

projectディレクトリへ移動

ShellScript
cd prohject

作業開始時間の確認

ShellScript
date +"%Y-%m-%d %H:%M:%S"

現在ブランチの確認

ShellScript
git branch

gitの状態確認

ShellScript
git status

現在のチェックアウトとリモートの差分確認

ShellScript
git log --oneline --no-merges HEAD..origin/develop

リモートから取得してきた最新のコミットをマージ

ShellScript
git merge origin/develop

しっかり再度マージされたか確認

ShellScript
git log --oneline --no-merges HEAD..origin/develop

ECCUBEの場合:プロキシー更新

ShellScript
php bin/console eccube:generate:proxies

ECCUBEの場合:プロキシー更新

ShellScript
php bin/console eccube:generate:proxies

ECCUBEの場合:キャッシュクリア

ShellScript
php bin/console cache:clear --no-warmup

ECCUBEの場合:プロキシー更新(Entity更新時のみでOK)

ShellScript
php bin/console eccube:generate:proxies

ECCUBEの場合:スキーマ更新(DBで項目追加や変更時のみでOK)

ShellScript
php bin/console doctrine:schema:update --dump-sql --force

ECCUBEの場合:全マイグレーション実行(マイグレーションある時のみでOK)

ShellScript
php bin/console doctrine:migrations:migrate

ECCUBEの場合:プロキシー更新

ShellScript
php bin/console eccube:generate:proxies

作業終了時間の確認

ShellScript
date +"%Y-%m-%d %H:%M:%S"
カテゴリー
EC-CUBE

【EC-CUBE4】1円ズレる原因

カスタマイズにより、マイナス伝票を作成していたプロジェクトで発生

通常の消費税計算へマイナス値を渡すと、切り捨て処理が反転する

[temp id=3]

消費税取得処理へ負数を使用すると端数処理が反転する。

対象コードを一部抜粋

ファイルパス:src/Eccube/Service/PurchaseFlow/Processor/TaxProcessor.php

PHP
<?php
// 税込表示の場合は, priceが税込金額のため割り戻す.
if ($item->getTaxDisplayType()->getId() == TaxDisplayType::INCLUDED) {
    $tax = $this->taxRuleService->calcTaxIncluded(
        $item->getPrice(), $item->getTaxRate(), $item->getRoundingType()->getId(),
        $item->getTaxAdjust());
} else {
    $tax = $this->taxRuleService->calcTax(
        $item->getPrice(), $item->getTaxRate(), $item->getRoundingType()->getId(),
        $item->getTaxAdjust());
}

端数を切り捨てにしている場合は、第三引数をnullにして繰切り上げにすれば良い

PHP
<?php
// 税込表示の場合は, priceが税込金額のため割り戻す.
if ($item->getTaxDisplayType()->getId() == TaxDisplayType::INCLUDED) {
    $tax = $this->taxRuleService->calcTaxIncluded(
        $item->getPrice(), $item->getTaxRate(), null,
        $item->getTaxAdjust());
} else {
    $tax = $this->taxRuleService->calcTax(
        $item->getPrice(), $item->getTaxRate(), null,
        $item->getTaxAdjust());
}
カテゴリー
EC-CUBE

【EC-CUBE4】価格を少数第二位まで登録する

卸価格で少数第二位まで使用する要件が上がった。

[temp id=3]

実装できるか調査

dtb_product_classのprice02に小数点が登録できるのは把握していた。

通過設定を変更

プログラムを調査していると、envの設定を変更すれば登録できるようになる事がわかった。

デフォルト(未定義):ECCUBE_CURRENCY=JPY

ドルへ変更:ECCUBE_CURRENCY=USD

管理画面:商品登録で少数第二位まで登録可能になった。

price01, price02両方ともに影響する。

各所円マークがドルマークへ変更される

price02のみ使用したい

PriceTypeのSCALEで、小数点以下の桁数を制御しているのがわかった。

ProductClassTypeExtensionを作成

app/Customize/Form/Extension/Admin/ProductClassTypeExtension.php

PHP
<?php
/**
 * price02へWholesalePriceTypeを適用する
 */
namespace Customize\Form\Extension\Admin;
use Customize\Form\Type\WholesalePriceType;
use Eccube\Form\Type\Admin\ProductClassType;
use Symfony\Component\Form\AbstractTypeExtension;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Common\EccubeConfig;
use Eccube\Entity\ClassCategory;
use Eccube\Form\DataTransformer;
use Eccube\Form\Type\Master\DeliveryDurationType;
use Eccube\Form\Type\Master\SaleTypeType;
use Eccube\Form\Type\PriceType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
class ProductClassTypeExtension extends AbstractTypeExtension
{
    /**
     * @var EntityManagerInterface
     */
    protected $entityManager;
    /**
     * @var EccubeConfig
     */
    protected $eccubeConfig;
    /**
     * ProductClassType constructor.
     *
     * @param EntityManagerInterface $entityManager
     */
    public function __construct(
        EntityManagerInterface $entityManager,
        EccubeConfig $eccubeConfig
    ) {
        $this->entityManager = $entityManager;
        $this->eccubeConfig = $eccubeConfig;
    }
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('code', TextType::class, [
                'required' => false,
                'constraints' => [
                    new Assert\Length([
                        'max' => $this->eccubeConfig['eccube_stext_len'],
                    ]),
                ],
            ])
            ->add('stock', NumberType::class, [
                'required' => false,
                'constraints' => [
                    new Assert\Regex([
                        'pattern' => "/^\d+$/u",
                        'message' => 'form_error.numeric_only',
                    ]),
                ],
            ])
            ->add('stock_unlimited', CheckboxType::class, [
                'label' => 'admin.product.stock_unlimited__short',
                'value' => '1',
                'required' => false,
            ])
            ->add('sale_limit', NumberType::class, [
                'required' => false,
                'constraints' => [
                    new Assert\Length([
                        'max' => 10,
                    ]),
                    new Assert\GreaterThanOrEqual([
                        'value' => 1,
                    ]),
                    new Assert\Regex([
                        'pattern' => "/^\d+$/u",
                        'message' => 'form_error.numeric_only',
                    ]),
                ],
            ])
            ->add('price01', PriceType::class, [
                'required' => false,
            ])
            ->add('price02', WholesalePriceType::class, [
            ])
            ->add('tax_rate', TextType::class, [
                'required' => false,
                'constraints' => [
                    new Assert\Range(['min' => 0, 'max' => 100]),
                    new Assert\Regex([
                        'pattern' => "/^\d+(\.\d+)?$/",
                        'message' => 'form_error.float_only',
                    ]),
                ],
            ])
            ->add('delivery_fee', PriceType::class, [
                'required' => false,
            ])
            ->add('sale_type', SaleTypeType::class, [
                'multiple' => false,
                'expanded' => false,
                'constraints' => [
                    new Assert\NotBlank(),
                ],
            ])
            ->add('delivery_duration', DeliveryDurationType::class, [
                'required' => false,
                'placeholder' => 'common.select__unspecified',
            ])
            ->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
                $form = $event->getForm();
                $data = $form->getData();
                if (empty($data['stock_unlimited']) && is_null($data['stock'])) {
                    $form['stock_unlimited']->addError(new FormError(trans('admin.product.product_class_set_stock_quantity')));
                }
            });
        $transformer = new DataTransformer\EntityToIdTransformer($this->entityManager, ClassCategory::class);
        $builder
            ->add($builder->create('ClassCategory1', HiddenType::class)
                ->addModelTransformer($transformer)
            )
            ->add($builder->create('ClassCategory2', HiddenType::class)
                ->addModelTransformer($transformer)
            );
    }
    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'Eccube\Entity\ProductClass',
        ]);
    }
    /**
     * {@inheritdoc}
     */
    public static function getExtendedTypes(): iterable
    {
        return [ProductClassType::class];
    }
}

PriceTypeをコピーして、SCALEを定数で2に設定したWholesalePriceTypeを作成

ファイルパス:app/Customize/Form/Type/WholesalePriceType.php

PHP
<?php
/**
 * 卸価格:price02専用Formクラス
 * 小数点第2位まで、登録できるように調整
 * 通貨タイプ:デフォルトJPYの場合は、小数点の桁数は0に設定されている
 */
namespace Customize\Form\Type;
use Eccube\Common\EccubeConfig;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Range;
class WholesalePriceType extends AbstractType
{
    const SCALE = 2;
    /**
     * @var EccubeConfig
     */
    protected $eccubeConfig;
    /**
     * @var ContainerInterface
     */
    protected $container;
    /**
     * PriceType constructor.
     *
     * @param EccubeConfig $eccubeConfig
     */
    public function __construct(EccubeConfig $eccubeConfig, ContainerInterface $container)
    {
        $this->eccubeConfig = $eccubeConfig;
        $this->container = $container;
    }
    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $currency = $this->container->getParameter('currency');
        $scale = self::SCALE;
        $max = $this->eccubeConfig['eccube_price_max'];
        $min = -$max;
        $constraints = function (Options $options) use ($max, $min) {
            $constraints = [];
            // requiredがtrueに指定されている場合, NotBlankを追加
            if (isset($options['required']) && true === $options['required']) {
                $constraints[] = new NotBlank();
            }
            if (isset($options['accept_minus']) && true === $options['accept_minus']) {
                $constraints[] = new Range([
                    'min' => $min,
                    'max' => $max,
                ]);
            } else {
                $constraints[] = new Range(['min' => 0, 'max' => $max]);
            }
            return $constraints;
        };
        $resolver->setDefaults(
            [
                'currency' => $currency,
                'scale' => $scale,
                'grouping' => true,
                'constraints' => $constraints,
                'accept_minus' => false, // マイナス値を許容するかどうか
            ]
        );
    }
    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return MoneyType::class;
    }
    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'price';
    }
}
カテゴリー
EC-CUBE

【EC-CUBE4】EC-CUBE2からデータ移行

バージョンは「2.11」からの結構カスタマイズされているサイトの移行となります。

どのように移行する?

特にDBの項目増やしたり、プラグインを入れたりしてなければ、データ移行プラグインで最低限移行できる。

データ構成を把握していて、SQLで変換スクリプトを作成して移行しても問題はない。

今回は、データ移行プラグインをカスタマイズして対応した。

2系のデータが多すぎてdumpで落ちる場合

サーバーのスペックにもよるが、dtb_order_detailで5万件以上+その他諸々でサーバー落ち

結局テーブル毎に一覧を取得し、データ移行プラグイン用にcsvを作成し対応

受注明細の消費税のズレ

税率が基本情報で設定されるので、受注明細に設定されているものを優先するように変更

app/Plugin/DataMigration4/Controller/Admin/ConfigController.php

PHP
// 2.4.4, 2.11, 2.12
if (isset($this->baseinfo) && !empty($this->baseinfo)) {
    // $value['tax_rate'] = $data['tax_rate'] = $this->baseinfo['tax'];
    // 商品別税率設定へ対応_dtb_order_detailの[tax_rule]があればそのまま移行
    $value['tax_rate'] = $data['tax_rate'] ? $data['tax_rate'] : $this->baseinfo['tax'];
    $data['point_rate'] = $this->baseinfo['point_rate'];
}

商品別税率機能

2系から移行すると「dtb_tax_rule」テーブルのproduct_class_idが設定されていないので、うまく表示できない

対応方法

商品規格を使用していなければ、productに対してproduct_classが1つなので、対象を取得してアップデートする

カスタムするコードのヒント

app/Customize/Repository/ProductClassRepository.phpへメソッドの追加

PHP
public function getTranslationData()
{
    $qb = $this->createQueryBuilder('pc');
    $qb->select('IDENTITY(pc.Product) AS product_id, pc.id AS product_class_id');
    return $qb->getQuery()->getArrayResult();
}

app/Plugin/DataMigration4/Controller/Admin/ConfigController.php

作成したメソッド呼び出して、加工して当て込む

PHP
/** @var array $productData */
$productData = $this->productClassRepository->getTranslationData();
$this->productIdProductClassId = array_column($productData, 'product_class_id', 'product_id');

if ($data['product_id'] != 0) {
    $productId = $data['product_id'];
    if (isset($this->productIdProductClassId[$productId])) {
        $value['product_class_id'] = $this->productIdProductClassId[$productId];
    }
}

改行コード

app/Plugin/DataMigration4/Controller/Admin/ConfigController.php

PHP
/**
 * 改行コードを変換
 */
public function convertToNewlineCode($staring) {
    $convert = [
        '\r' => "\r",
        '\n' => "\n",
    ];
    
    $target = array_keys($convert);
    $replace = array_values($convert);
    
    return str_replace($target, $replace, $staring);
}

/* 下記のような項目は変換が必要な場合もある */
$data['main_list_comment'];
$data['main_comment'];
$data['comment3'];
$data['body'];