カテゴリー
システム開発技術 マイグレーション

【マイグレーション】migration

まったりのんびり、@vVv_kenshi_vVvです!

EC-CUBE4の開発でよく使用するので、記事にしています。

注意事項

私の経験則で書いている事なので、すべて正しいというわけではございませんのでご了承くださいませ。

エスケープに注意

dtb_csvのカラムに「entity_name」があり「//」ダブルスラッシュで登録されています。

phpとsqlで2回エスケープされるみたいで「////////」8個記述しなければ「//」になりません。

ちなみに「/」で登録されても機能します。

プラグインなどは「/」で追加登録される事が多いみたいです。

マイグレーションで非推奨作業

何でもかんでもマイグレーションで、やらない事

  • テーブルは作成しない
  • テーブルは削除しない
  • テーブルのカラム「追加・削除」はしない
  • テーブルのカラム内容変更はしない

EC-CUBE4でカスタマイズするなら、上記の対応はスキーマの更新で可能です。

上記のようなマイグレーションを使用した後に、スキーマを更新したりプラグインをインストールや削除したりすると、Entityの方へ書き換えられて意図しないバグが発生する可能性があります。

スキーマの更新

対象のEntityの内容を変更してスキーマ更新コマンドで可能です。

スキーマの更新内容確認コマンド

Bash
php  bin/console doctrine:schema:update --dump-sql

スキーマ更新コマンド

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

migrationコマンド一覧

ついつい調べてしまう、忘れっぽいあなたに捧げる記事です。

先頭の「php」は、サーバーの設定によってログインユーザーでは権限で弾かれる可能性があるので「php」から実行しています。

マイグレーションを実行すると「migration_versions」へデータが登録されます。

データを削除し、マイグレーションを流し直しも可能です。

SQL
DELETE FROM migration_versions WHERE version = 'XXXX'

全ての実行されていないマイグレーション実行

Bash
php bin/console doctrine:migrations:migrate

マイグレーションファイルを指定して実行

Bash
php bin/console doctrine:migrations:execute 2021XXXXXXXXXX  --down 
php bin/console doctrine:migrations:execute 2021XXXXXXXXXX  --up

マイグレーションの状態確認

Bash
php bin/console doctrine:migrations:status

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

Bash
php bin/console doctrine:migrations:generate

マイグレーション履歴の削除

Bash
php bin/console doctrine:migrations:version 2021XXXXXXXXXX --delete

マイグレーションファイル

コマンドで作成したマイグレーションファイル

PHP
<?php declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
 * Auto-generated Migration: Please modify to your needs!
 */
final class Version20220105152818 extends AbstractMigration
{
    public function up(Schema $schema) : void
    {
        // this up() migration is auto-generated, please modify it to your needs

    }

    public function down(Schema $schema) : void
    {
        // this down() migration is auto-generated, please modify it to your needs

    }
}

定数やDBからデータ取得も可能

サンプルコード:dtb_csvへ項目追加

PHP
final class Version2022XXXXXXXXXX extends AbstractMigration
{

    const ENTITY_NAME = 'Eccube\\\Entity\\Product';
    const FIELD_NAME = 'new_column';

    public function up(Schema $schema) : void
    {        
        $this->addSql("INSERT INTO dtb_csv (csv_type_id, creator_id, entity_name, field_name, reference_field_name, disp_name, sort_no, enabled, create_date, update_date, discriminator_type) VALUES ('1', null, 'Eccube////////Entity////////Product', 'new_column', 'new_column', '新規項目', '10', '1', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'csv');");
    }

    public function down(Schema $schema) : void
    {
        $_ = function($s){return $s;};

        $targetId = $this->connection->fetchColumn("SELECT id FROM dtb_csv WHERE entity_name = '{$_(self::ENTITY_NAME)}' AND field_name = '{$_(self::FIELD_NAME)}'");

        if (!empty($targetId)) {
            $this->addSql("DELETE FROM dtb_csv WHERE id = $targetId;"); 
        }

   }
}

配列も取得可能

PHP
$targetId = $this->connection->fetchColumn(・・・);

$targetId = $this->connection->fetchArray(・・・);
カテゴリー
EC-CUBE

【EC-CUBE4】注文ステータス追加

[temp id=3]

コンビニ支払いのステータス追加

mtb_order_statusのid2が空いているので使用する

DB(テーブル)にデータ追加

  • mtb_order_status:入金待ち追加
  • mtb_order_status_color:入金待ちカラー追加
  • mtb_customer_order_status:入金待ち追加

OrderStatus(Entity)へ定数

本体ソースに追加しするか、継承クラスで定数を追加する

Traitには定数を追加できない。

定数「WAIT_PAYMENT」の追加

PHP
<?php
 namespace Customize\Entity;

 use Eccube\Entity\OrderStatus as BaseEntity;

 if (!class_exists('Customize\Entity\OrderStatus')) {

  /** 親クラスの定数宣言を拡張する目的に作成しています */
  class OrderStatus extends BaseEntity {
     /** 入金待ち */
     const WAIT_PAYMENT = 2;
     }
 }

注文ステータス遷移設定

app/config/packages/order_state_machine.php

編集箇所抜粋

PHP
'places' => [
     (string) Status::NEW,
     (string) Status::WAITI_PAYMENT,
     (string) Status::CANCEL,
     (string) Status::IN_PROGRESS,
     (string) Status::DELIVERED,
     (string) Status::PAID,
     (string) Status::PENDING,
     (string) Status::PROCESSING,
     (string) Status::RETURNED,
     (string) Status::CANCEL_ENTRY,
     (string) Status::CANCEL_PROCESSING
 ],

入金待ちから変更できるステータスの追加

※複数の場合は「配列で渡す」

PHP
'transitions' => [
    'pay' => [
        'from' => (string) Status::NEW,
        'from' => [(string) Status::NEW, (string) Status::WAIT_PAYMENT],
        'to' => (string) Status::PAID,
    ],
    'packing' => [
        'from' => [(string) Status::NEW, (string) Status::PAID, (string) Status::CANCEL_ENTRY],
        'to' => (string) Status::IN_PROGRESS,
    ],
    'cancel' => [
        'from' => [(string) Status::NEW, (string) Status::IN_PROGRESS, (string) Status::PAID, (string) Status::CANCEL_PROCESSING],
        'to' => (string) Status::CANCEL,
    ],
    'back_to_in_progress' => [
        'from' => (string) Status::CANCEL,
        'to' => (string) Status::IN_PROGRESS,
    ],
    'ship' => [
        'from' => [(string) Status::NEW, (string) Status::PAID, (string) Status::IN_PROGRESS, (string) Status::CANCEL_ENTRY],
        'to' => [(string) Status::DELIVERED],
    ],
    'return' => [
        'from' => (string) Status::DELIVERED,
        'to' => (string) Status::RETURNED,
    ],
    'cancel_return' => [
        'from' => (string) Status::RETURNED,
        'to' => (string) Status::DELIVERED,
    ],
    'cancel_entry' => [
        'from' => [(string) Status::NEW, (string) Status::IN_PROGRESS, (string) Status::PAID, (string) Status::DELIVERED, (string) Status::CANCEL_PROCESSING, (string) Status::WAIT_PAYMENT],
        'to' => (string) Status::CANCEL_ENTRY,
    ],
    'cancel_processing' => [
        'from' => (string) Status::CANCEL_ENTRY,
        'to' => (string) Status::CANCEL_PROCESSING,
    ],
],

OrderStateMachineでステータス変更処理

キャンセルの場合は、在庫やポイントを戻してくれる

PHP
$this->orderStateMachine->apply($Order, $changeStatus);

OrderStateMachineでステータスの処理を追加

在庫を戻したり、ポイントの減算処理も追加できる

PHP
    public static function getSubscribedEvents()
    {
        return [
            'workflow.order.completed' => ['onCompleted'],
            'workflow.order.transition.pay' => ['updatePaymentDate'],
            'workflow.order.transition.cancel' => [['rollbackStock'], ['rollbackUsePoint']],
            'workflow.order.transition.back_to_in_progress' => [['commitStock'], ['commitUsePoint']],
            'workflow.order.transition.ship' => [['commitAddPoint']],
            'workflow.order.transition.return' => [['rollbackUsePoint'], ['rollbackAddPoint']],
            'workflow.order.transition.cancel_return' => [['commitUsePoint'], ['commitAddPoint']],
            // 処理が必要であればここで定義
            // 'workflow.order.transition.cancel_entry' => [],
            // 'workflow.order.transition.cancel_processing' => [],
        ];
    }

決済処理中について

EC-CUBE4では、「決済処理中」ステータスがあり在庫を確保している状態です。

決済途中などで、エラーやサイトを閉じたりして発生しずっと受注が残るので、キャンセルして在庫の調整が必要になる。

カテゴリー
EC-CUBE

【EC-CUBE4】エラーリスト

エラーの解決方法をメモする。

ローカル環境構築関連

WARNING [cache] Failed to save key

事象1:DockerでカスタマイズしたCommand実行で発生した

事象2:AWSとソニーペイメントプラグインを使用していて、cron実行で発生した

原因:AWSのELBを挟んだ場合、REMOTE_ADDRで正しいIPが取得できない

プロジェクト名/app/Plugin/SlnPayment4/Service/Utill.php

修正前ソース

    public function GetLogInfo()
    {        
        $msg = '[{' . $_SERVER['SCRIPT_NAME'] . '}';
        
        $msg .= 'from {' . $_SERVER['REMOTE_ADDR'] . "}\n";
         ・
         ・
         ・

修正後ソース

    public function GetLogInfo()
    {        
        $msg = '[{' . $_SERVER['SCRIPT_NAME'] . '}';

        if(isset($_SERVER['REMOTE_ADDR'])){
            $msg .= 'from {' . $_SERVER['REMOTE_ADDR'] . "}\n";
        } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            // aws_cron対応
            $msg .= 'from {' . $_SERVER['HTTP_X_FORWARDED_FOR'] . "}\n";
        } else {
            // ローカル対応
            $msg .= 'from {' . '['.'localhost'.']' ."\t" . "}\n";
        }

ELB + K8S環境でingress-nginxを通した場合

$_SERVER['HTTP_X_ORIGINAL_FORWARDED_FOR']

参考サイト:https://uiuifree.com/blog/develop/php-elb-ip-address/

No composer.json present in the current directory, this may be the cause of the following exception.

事象:「docker-compose up -d」コマンド実行で発生

原因:composerのバージョンが対応していないのでエラーみたいです。

ファイル名:プロジェクト名/Dockerfile

修正後ソース

RUN curl -sS https://getcomposer.org/installer \
  | php \
  && mv composer.phar /usr/bin/composer \
  && composer selfupdate --1 \ ←これ!!!
  && composer config -g repos.packagist composer https://packagist.jp \
  && composer global require hirak/prestissimo \
  && chown www-data:www-data /var/www \
  && mkdir -p ${APACHE_DOCUMENT_ROOT}/var \
  && chown -R www-data:www-data ${APACHE_DOCUMENT_ROOT} \
  && find ${APACHE_DOCUMENT_ROOT} -type d -print0 \
  | xargs -0 chmod g+s \
  ;

Unable to replace alias “session.handler” with actual definition “session.handler.memcached”

事象:サーバーからPULLしたソースでローカル環境構築

原因:handler_idの設定値が正しくない(古い?)

ファイル名:プロジェクト名/app/config/eccube/packages/framework.yaml

修正後ファイル

framework:
    secret: '%env(ECCUBE_AUTH_MAGIC)%'
    default_locale: '%locale%'
    translator:
      fallback: ['%locale%']
    csrf_protection: { enabled: true }
    http_method_override: true
    trusted_hosts: ~
    # https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
    session:
        # ↓ handler_id: session.handler.memcached ↓
        handler_id: 'Eccube\Session\Storage\Handler\SameSiteNoneCompatSessionHandler'
        save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
        name: '%env(ECCUBE_COOKIE_NAME)%'
        cookie_lifetime: '%env(ECCUBE_COOKIE_LIFETIME)%'
        gc_maxlifetime: '%env(ECCUBE_GC_MAXLIFETIME)%'
        cookie_httponly: true

You have requested a non-existent parameter “kernel.secret”. Did you mean this: “kernel.charset”?

事象:サーバーからプルしたものをローカルで立ち上げようとしたら、発生したエラー

原因:パラメータが定義されているframework.yamlファイルがない

ファイル名:プロジェクト名/app/config/eccube/packages/framework.yaml

作成ファイル

framework:
    secret: '%env(ECCUBE_AUTH_MAGIC)%'
    default_locale: '%locale%'
    translator:
      fallback: ['%locale%']
    csrf_protection: { enabled: true }
    http_method_override: true
    trusted_hosts: ~
    # https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
    session:
        handler_id: 'Eccube\Session\Storage\Handler\SameSiteNoneCompatSessionHandler'
        save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
        name: '%env(ECCUBE_COOKIE_NAME)%'
        cookie_lifetime: '%env(ECCUBE_COOKIE_LIFETIME)%'
        gc_maxlifetime: '%env(ECCUBE_GC_MAXLIFETIME)%'
        cookie_httponly: true

    # When using the HTTP Cache, ESI allows to render page fragments separately
    # and with different cache configurations for each fragment
    # https://symfony.com/doc/current/book/http_cache.html#edge-side-includes
    esi: { enabled: true }
    fragments: { enabled: true }
    php_errors:
        log: true
    assets:
      base_path: '/html/template/%eccube.theme%'
      packages:
        admin:
          base_path: '/html/template/admin'
        save_image:
          base_path: '/html/upload/save_image'
        plugin:
          base_path: '/html/plugin'
        install:
          base_path: '/html/template/install'
        temp_image:
          base_path: '/html/upload/temp_image'
        user_data:
          base_path: '/html/user_data'
        # json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'
    cache:
        # this value is used as part of the "namespace" generated for the cache item keys
        # to avoid collisions when multiple apps share the same cache backend (e.g. a Redis server)
        # See https://symfony.com/doc/current/reference/configuration/framework.html#prefix-seed
        prefix_seed: ec-cube
    # The 'ide' option turns all of the file paths in an exception page
    # into clickable links that open the given file using your favorite IDE.
    # When 'ide' is set to null the file is opened in your web browser.
    # See https://symfony.com/doc/current/reference/configuration/framework.html#ide
    ide: ~
    validation: { enable_annotations: true }
    templating: { engines: ['twig'] }

参考サイト

https://github.com/EC-CUBE/ec-cube/blob/4.0.5/app/config/eccube/packages/framework.yaml#L2

Place “2” is not valid for workflow “order”.

事象:注文ステータス追加で発生

原因:ステータス遷移の制御設定が必要

ファイル名:プロジェクト名/app/config/packages/order_state_machine.php

カテゴリー
EC-CUBE

【EC-CUBE4】SQL

便利そうなSQLをメモしていこうと思います。

調査用SQL

共通テンプレート適用

layout_idがないデータは、dtb_page_layoutで設定して確認

SQL
USE eccubedb;
SELECT 
 P.id page_id
 ,PL.layout_id
 ,L.layout_name
 ,P.page_name
 ,P.file_name
FROM  dtb_page P
LEFT JOIN dtb_page_layout PL ON P.id = PL.page_id
LEFT JOIN dtb_layout L ON PL.layout_id = L.id;

データ削除

注文データ関連削除SQL

実際に削除する際は、バックアップ取るなど必ず確認して下さい!

SQL
USE eccubedb;
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE dtb_cart;
TRUNCATE TABLE dtb_cart_item;
TRUNCATE TABLE dtb_order;
TRUNCATE TABLE dtb_order_item;
TRUNCATE TABLE dtb_shipping;
-- ソニーペイメント
TRUNCATE TABLE plg_sln_order_payment_history;
TRUNCATE TABLE plg_sln_order_payment_status;
-- ソニーペイメント定期購入
TRUNCATE TABLE plg_sln_regular_order;
TRUNCATE TABLE plg_sln_regular_order_item;
TRUNCATE TABLE plg_sln_regular_shipping;
TRUNCATE TABLE plg_sln_regular_order_to_order;
SET FOREIGN_KEY_CHECKS = 1;

外部キー制約の無効化, 有効化

関連するデータがある場合は、削除する順序が正しくない場合はエラーになるので、こちらを入れてます。

SQL
SET FOREIGN_KEY_CHECKS = 0;
SET FOREIGN_KEY_CHECKS = 1;
カテゴリー
Ark

【ARK】樹液を簡単に集める方法

樹液の取得方法を載せていきます。

樹液の取得方法

レッドウッドの木で蛇口を設置して、樹液を集める方法があります。

今回は紹介するのは、それ以外の方法です。

樹液の蛇口も取るためのハシゴなどの建造物も不要です。

雪山で樹液

Crystal Islesで確認しましたが、中央の太い木からたまに出ます。

クリスタルワイバーンで取得できました。

ARK_雪山樹液

砂漠で樹液

Crystal Islesで確認しましたが、先端がもさもさしている木からたまに出ます。

Scorched Earthにもあるみたいです。

ARK_砂漠樹液
カテゴリー
Ark

【Ark】クリスタルアイルズ:アーティファクト場所

[temp id=3]

アーティファクトのスクショ載せてきまーす!!

見つけてないのもあるのでご了承ください。

アーティファクト

クリスタルアイルズのアーティファクトは、他のマップと違い洞窟攻略はありません。

その場所に行って取得するだけなので比較的簡単に集める事が可能です。

見つけられていないのもあります、、、

野獣

ARK_CrystalIsle_野獣

門番

ARK_CrystalIsle_門番

免疫

ARK_CrystalIsle_免疫

暴食

ARK_CrystalIsle_暴食

天帝

ARK_CrystalIsle_天帝

狩人

ARK_CrystalIsle_狩人
カテゴリー
育児ブログ

【育児】買って良かったおもちゃリスト

[temp id=3]

お子様によっては好き嫌いもあると思います。

私の子基準でリストアップします。

2ヶ月から

歯固め

バナナの歯固め!めっちゃ可愛い!!

こんなのがあるなんて知らずに5ヶ月の時に購入しました。

6ヶ月になる頃には噛む力が上がりギュッギュなるようになりました。

https://amzn.to/3nohS6p

オーボール

持ちやすさが舌触りが良いのかお気に入りです。

回転させながら上に投げても大喜びです。

https://amzn.to/3qQiuVb

ビーズクッション小

音や柔らかさがお気に入りのようです。

お腹の上で転がしたり、ビーズクッションを叩いたりしても楽しんでくれます。


布絵本

カサカサ音袋の音が好きで、掴んだら離しません。

タグや歯固めも使い始めます。

https://amzn.to/3hQ1j1V

4ヶ月から

アンパンマン

色合いとカサカサ音と鏡が結構お気に入り٩(•౪•٩)三

https://amzn.to/3qSntVt

6ヶ月から

ジャンパルー

5ヶ月で購入したが怖くて楽しめず、、、

6ヶ月に近づくと楽しんて乗れるようになった٩(•౪•٩)三


風船

もっと早くても良いかもしれない

記念撮影で大きい風船を使用した時に渡してみたが、掴みづらく遊べないようだった

長細いのなら良いかなと思い購入したら喜んで遊んでもらえた

https://amzn.to/3omzSiF

カテゴリー
住宅

【住宅】ソーラーパネル収入

[temp id=3]

住宅購入の際にソーラーパネルを勧められて、設置することにしました。

どのぐらい収入が入るのか、不安な気持ちがありましたので参考までに展開します。

ソーラーパネルの毎月の収入

1万円ぐらい収入があると予想していたが、
意外に電気を使用していたようで4000円ぐらいになった。

千葉県在住です。

屋根へ3箇所のソーラパネルを設置しています。

2020年売電量発電量買電量収入電気代
10月212kwh316kwh420kwh4,221円16,971円
11月88kwh245kwh553kwh4,662円25,955円
12月150kwh261kwh1012kwh1,890円34,151円
2021年売電量発電量買電量収入電気代
1月1,869円24,736円
2月3,906円21,561円
3月5,586円
4月

70kwhぐらい違うのに400円しか変わらないのは、、、

確認中

カテゴリー
EC-CUBE

【EC-CUBE4】リポジトリー:Repository

[temp id=3]

ドキュメント読んで、手順通りに学んだわけではないので参考程度に見てください。

Repository拡張方法

基本的に本体のソースはアップデートで変更になる可能性があるので、拡張して使用するのが安全です。

新規Repositoryファイルを作成

ファイル保存場所:Customize\Repository\ProductRepository.php

・Repositoryファイル「ProductRepository.php」を作成

<?php

namespace Customize\Repository;

use Eccube\Repository\ProductRepository as BaseRepository;

class ProductRepository extends BaseRepository
{
    /**
     * 新規メソッドの作成
     *
     * @param null|array $ProductStatus 指定の商品ステータス
     *
     * @return Products[] 商品の配列の配列
     */
    public function getProductList($ProductStatus = null)
    {
        $qb = $this->createQueryBuilder('p');

        if ($ProductStatus) {
            $qb
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
                ->setParameter('Status', $ProductStatus);
        }

        $Products = $qb->getQuery()->getResult();

        return $Products;
    }

}

・拡張するRepositoryをuse(読込み)

・extendsで拡張

本体Repositoryの拡張

・メソッド毎コピー

・必要ファイルの読込み&construct定義

設定ファイルに定義

設定ファイル:app/config/eccube/services.yaml

・新規Repositoryファイル「ProductRepository.php」を作成

・拡張するRepositoryを定義する

services:
     ・
     ・
     ・
    Customize\Repository\ProductRepository:
        decorates: Eccube\Repository\ProductRepository

データの更新がうまくいかない

カスタマイズ案件で「dtb_cart」「dtb_cart_item」に似たテーブルを作った時の事。

登録直後の「cart_item」が表示されない挙動になった。

・F5で更新すれば表示される

・DBには「cart」「cart_item」が登録されている

結論を言うとcartクラスを更新すれば問題なし!!

$this->entityManager->refresh($cart)

登録の流れ

cart登録

cart_item登録

cart_item登録後なのでcartに紐づいていないcart_itemがデータになっている。

cart情報を取得しなおせば解決

カテゴリー
家庭菜園

【家庭菜園】シャインマスカット

[temp id=3]

家庭菜園を行っていきたいと思います。٩(•౪•٩)三

まぁArkでもマインクラフトでもゾンビアイランドでも経験済みです٩(๑’ꇴ’๑)۶

2020/10/29 苗木の誕生日

どんな苗にしたか

選別の結果!!!

https://amzn.to/32pwzP4

4,235円で購入٩(•౪•٩)三

苗木特徴
  1. 高さ40cm
  2. 最大10cmの葉10枚
  3. 虫に食べられた痕?

素人なので高さの測り方違う!?

シャインマスカット植え替え

10月〜11月が良いみたいです。

植木鉢は大きめのこちらにしました↓

https://amzn.to/2OKgXlz

根っこについた土を落とす

根っこを千切らないように優しく手でほぐしながら、落としていきます。

鉢に植え付け

好みの土壌:石灰分が多い痩せた水はけの良い土

赤玉土

https://amzn.to/3a7kt0V

腐葉土

https://amzn.to/3ee7EDh

ようりんとけい酸入りの肥料を入れます

https://amzn.to/3sbt88x

葉が穴だらけで大丈夫!?

結論から言うと問題なかったです。

結局葉っぱは全て枯れ落ちました

12月頃枯れ落ちて、3月に芽がつきました!

そして栄養の分配考慮して、一番上の枝を剪定する時に一番上の新芽がポロっと落ちた◟꒰◍´Д‵◍꒱◞

成長

2週間ぐらいで9cmぐらい伸びてる