ECCube4メモ

ちょっと触ったので。 必要となる前提知識が多すぎて初学者には辛い。

ECCube4公式サイト
ECCube4機能一覧






画面に受け渡されたデータを確認する




xxxxController::indexの戻り値がtwigに受け渡される。
Project/app/template/admin/Product/product.twig

{{ dump(Product) }}
{{ dump(xxxx) }} をtwigに埋め込むと値が画面に表示される。



レイアウトのカスタマイズ



画面の表示を変える場合。

twigファイルをコピーする。
コピーしたtwigファイルを変更する。
src/Eccube以下を極力触らないようにすることでバージョンアップが比較的容易になる。

src/Eccube/Resource/template/admin/Product/product.twig

app/template/admin/Product/product.twig



コントローラのカスタマイズ



ルーティングの変更、追加など。
処理は極力書かない。

https://sachips.byeto.jp/eccube/product-detail-categories-disp.html

ProductContorollerの例

src/Eccube/Controller/Admin/Product/ProductController.php
から
app/Customize/Controller/Admin/Product/CustomizeProductController.php
へコピー

CustomizeProductController.php
のnamespaceとクラス名を編集


namespace Customize\Controller\Admin\Product;

class CustomizeProductController


ルーティングが上書きされてカスタムされた機能が動作するようになる。
コンストラクタなど必要なものを残しルーティング等不要なものを削除。



画面に表示する項目を追加する



フォームに追加
https://doc4.ec-cube.net/customize_formtype
を参考にする、

use

使用する項目をuse

use Eccube\Common\EccubeConfig;
use Eccube\Form\Type\Admin\ProductType;
use Plugin\Maker4\Entity\Maker;
use Plugin\Maker4\Repository\MakerRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints as Assert;

use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;

__construct


初期化処理。データ取得のためのリポジトリを受け渡す。

ウィジェットタイプ


TextType テキストフィールド
ChoiceType セレクト・ラジオ
BirthdayType 日付

vendor/symfony/form/Extension/Core/Type/以下を確認する。

symfonyのドキュメントを確認してもいい。
https://symfony.com/doc/current/forms.html

プラグイン等を参考にするとわかりやすい。

buildForm


拡張ウィジェットの追加

/**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('Maker_ship', EntityType::class, [
                'label' => 'maker.admin.product_maker.maker',
                'class' => Maker::class,
                'choice_label' => 'name',
                'choices' => $this->makerRepository->findBy([], ['sort_no' => 'DESC']),
                'required' => false,
                'eccube_form_options' => [
                    'auto_render' => false,
                ],
            ]);
    }

Maker_shipウィジェットを追加できるようになる。
twigにMaker_ship追加。

<div class="row">
    <div class="col-3">
        <div class="d-inline-block" data-tooltip="true" data-placement="top"
                title="{{ 'tooltip.product.delivery_duration'|trans }}">
            <span>{{ 'admin.product.maker_id_ship'|trans }}</span>
        </div>
    </div>
    <div class="col mb-2">
        <div>
            {{ form_widget(form.Maker_ship) }}
        </div>
    </div>
</div>



ファイルの読み出し順



カスタム → 標準 → プラグインの順に読み込まれる。
ECCUBEROOT/app/template/[template_code]
ECCUBEROOT/src/Eccube/Resource/template/[template_code]
ECCUBEROOT/app/Plugin


twig上でデータ取得



https://umebius.com/eccube/use-repository-from-twig/



builderについて



builderサンプル


セレクト・ラジオ

use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

クラスからセレクト
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
        $builder
            ->add('Maker_ship', EntityType::class, [
                'label' => 'maker.admin.product_maker.maker',
                'class' => Maker::class,
                'choice_label' => 'name',
                'choices' => $this->makerRepository->findBy([], ['sort_no' => 'DESC']),
                'required' => false,
                'eccube_form_options' => [
                    'auto_render' => false,
                ],
            ]);

テキストフィールド

use Symfony\Component\Form\Extension\Core\Type\TextType;
        $builder
            ->add('maker_url', TextType::class, [
                'label' => 'maker.admin.product_maker.maker_url',
                'required' => false,
                'attr' => [
                    'maxlength' => $this->eccubeConfig['eccube_url_len'],
                    'placeholder' => 'maker.admin.placeholder.url',
                ],
                'eccube_form_options' => [
                    'auto_render' => true,
                ],
                'constraints' => [
                    new Assert\Url(),
                    new Assert\Length(['max' => $this->eccubeConfig['eccube_url_len']]),
                ],
            ]);

カレンダー入力

use Symfony\Component\Form\Extension\Core\Type\BirthdayType;

        $builder
            ->add('birth', BirthdayType::class, [
                'required' => false,
                'input' => 'datetime',
                'years' => range(date('Y'), date('Y') - $this->eccubeConfig['eccube_birth_max']),
                'widget' => 'single_text',
                'format' => 'yyyy-MM-dd',
                'placeholder' => ['year' => '----', 'month' => '--', 'day' => '--'],
                'constraints' => [
                    new Assert\LessThanOrEqual([
                        'value' => date('Y-m-d', strtotime('-1 day')),
                        'message' => 'form_error.select_is_future_or_now_date',
                    ]),
                ],
            ])


引数について


id
第1引数
twigでしているつ時に利用する。
重複不可

ウィジェットタイプ
第2引数
代表的なものは以下

EntityType::class
クラス(DB) からセレクト、ラジオ
TextType::class
テキストフィールド
ChoiceType::class
変数で指定したセレクト、ラジオ

オプション
第3引数
label, required, class, choice_label, placeholder, data, constraints 等が指定できる。

label
ラベル、表示するテキスト

required
必須項目の設定
falseにするとSelect,RadioでNoneが表示されるようになる。

class
EntityType::classのとき必要
紐づけるEntityを指定

choice_label
EntityType::classのとき必要
'name'を指定した場合カラム:'name'がラベルとして表示される。

placeholder
値を設定するとセレクト、ラジオ, セレクトのNoneを上書き。
falseに設定するとセレクト、ラジオ, セレクトのNoneがなくなる。

data
値を指定する。
DBの値が常に上書きされるので使用しない。

constraints
バリデーション

URL形式
new Assert\Url(), 


文字数制限
new Assert\Length(['max' => $this->eccubeConfig['eccube_url_len']]),

必須項目

'constraints' => [
                    new Assert\NotBlank()
                ],

正規表現
'constraints' => [
                    new Assert\Regex(array(
                        'pattern' => "/^[ァ-ヶヲ-゚ー]+$/u",
                    )),
                ],

formtypeについて



https://symfony.com/doc/current/reference/forms/types.html


eccube_form_options=> auto_render
trueの場合twigに記述しなくても画面に表示される。

指定可能なオプションは以下

Defined options are:
"action", "allow_extra_fields", "allow_file_upload", "attr", "auto_initialize", "block_name", "by_reference", "choice_attr", "choice_label", "choice_loader", "choice_name", "choice_translation_domain", "choice_value", "choices", "choices_as_values", "compound", "constraints", "csrf_field_name", "csrf_message", "csrf_protection", "csrf_token_id", "csrf_token_manager", "data", "data_class", "disabled", "eccube_form_options", "empty_data", "error_bubbling", "error_mapping", "expanded", "extra_fields_message", "group_by", "help", "inherit_data", "invalid_message", "invalid_message_parameters", "label", "label_attr", "label_format", "mapped", "method", "multiple", "placeholder", "post_max_size_message", "preferred_choices", "property_path", "required", "translation_domain", "trim", "upload_max_size_message", "validation_groups".


builderで初期値を設定する


use Eccube\Entity\Product;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

        // タイムセール対象区分
        $builder
        ->add('test', ChoiceType::class, [
            'label' => 'admin.product.test',
            'choices' => ["しない" => 0, "する" => 1],
            'compound' => true,
            'expanded' => true,
            'required' => false,
            'placeholder' => false,
            'eccube_form_options' => [
                'auto_render' => false,
            ]
        ]);

        $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
            $data = $event->getData();
            if (!$data instanceof Product) {
                return;
            }
            $form = $event->getForm();
            if (is_null($form['test']->getData())) {
                $form['ts_flag']->setData(0);
            }
        });

リスナを追加して、データベースから値を持ってくるタイミングでNULLチェックをしている。


builderから自動挿入時に必須ラベルを追加する


Form/xxxTypeExtension を編集する。

必須項目は
'required' => true,
を指定する。

必須でない項目は
'required' => false,
'placeholder' => false,

を指定する。

twig ファイルを編集する。
{# エンティティ拡張の自動出力 #} を書き換え

{# エンティティ拡張の自動出力 #}
{% for f in form if f.vars.eccube_form_options.auto_render %}
    {% if f.vars.eccube_form_options.form_theme %}
        {% form_theme f f.vars.eccube_form_options.form_theme %}
        {{ form_row(f) }}
    {% else %}
        <div class="row">
            <div class="col-3">
                <span>{{ f.vars.label|trans }}</span>
                <span class="badge badge-primary ml-1">
                    {{ 'admin.common.required'|trans }}
                </span>
            </div>
            <div class="col mb-2">
                <div>
                    {{ form_widget(f) }}
                    {{ form_errors(f) }}
                </div>
            </div>
        </div>
    {% endif %}
{% endfor %}
↓

{# エンティティ拡張の自動出力 #}
{% for f in form if f.vars.eccube_form_options.auto_render %}
    {% if f.vars.eccube_form_options.form_theme %}
        {% form_theme f f.vars.eccube_form_options.form_theme %}
        {{ form_row(f) }}
    {% else %}
        <div class="row">
            <div class="col-3">
                <span>{{ f.vars.label|trans }}</span>
                {% if f.vars.required %}
                    <span class="badge badge-primary ml-1">
                        {{ 'admin.common.required'|trans }}
                    </span>
                {% else %}
            </div>
            <div class="col mb-2">
                <div>
                    {{ form_widget(f) }}
                    {{ form_errors(f) }}
                </div>
            </div>
        </div>
    {% endif %}
{% endfor %}





メッセージのカスタマイズ



https://a-zumi.net/eccube4-customize-translation/

app/config/eccube/packages/translation.yaml 書き換え

framework:
    default_locale: '%locale%'
    translator:
        paths:
            - '%kernel.project_dir%/src/Eccube/Resource/locale/'
            - '%kernel.project_dir%/app/Customize/Resource/locale/'
        fallbacks:
            - '%locale%'

app/Customize/Resource/locale/
に追加、変更するメッセージを記述。

translation.yaml はバージョンアップ時に書き変わる



データ操作について



Doctrineを使用している。

データを取得する
$ships = $this->shippingRepository->findBy(['id' => $ids], ['id' => 'ASC']);
foreach ($ships as $ship) {
     echo($ship->getId());
}

データを取得する場合get + カラム名(キャメルケース)

第1引数は検索条件
第2引数はソート条件
第3引数は件数
第4引数はオフセット


joinする
        $qb = $this->createQueryBuilder('o')
            ->select('o, s')
            ->addSelect('oi', 'pref')
            ->leftJoin('o.OrderItems', 'oi')
            ->leftJoin('o.Pref', 'pref')
            ->innerJoin('o.Shippings', 's');
$thisはxxxxRepository

whereで絞り込む
$ids = [1, 3, 5];
$qb = $this->shippingRepository->createQueryBuilder('ship');
$qb->select('ship')
    ->where('ship.id in (:id)')
    ->setParameter('id', $ids);
$ships = $qb->getQuery()->getResult();



データを更新する
$ship->setTest(0);

$this->entityManager->persist($ship);
$this->entityManager->flush();

データ全体をダンプする
            $ships = $this->shippingRepository->findBy(['id' => $ids], ['id' => 'ASC']);
            foreach ($ships as $ship) {
               echo '
';
                   \Doctrine\Common\Util\Debug::dump($ships, 3);
               echo '
'; }



ログの確認・出力



log_info('ログメッセージ');
log_emergency()
log_alert()
log_critical()
log_error()
log_warning()
log_notice()
log_info()
log_debug()

ログの確認、削除。
rm /var/www/html/var/log/dev/site.log
less /var/www/html/var/log/dev/site.log





エラーになる場合



Whoops, looks like something went wrong

キャッシュを削除する
rm -rf /var/www/html/var/cache/dev/*

composer clear-cache
composer dump-autoload

Compile Error: Symfony\Component\Debug\DebugClassLoader::loadClass(): Failed opening required

上記手順で治らない場合

http://coelacanth.jp.net/ec-cube4_debugclassloader_error/


vendor/composer/autoload_classmap.php
vendor/composer/autoload_static.php
を編集。



というかBloggerの管理画面のデザインがひどいことになってる。戻せたからいいけど。

2020年6月27日土曜日