EC-CUBE3で頻繁に出てくる$appにセットされているもの

EC-CUBE3ではSilexを利用しているため、お作法としてApplication.phpを起点に処理を行っています。

ではControllerで$appと頻繁に使われているこの変数(twigだとappのことです)には何がセットされているのかを見てみましょう。

表示の仕方は、3.0.8からの機能になりますがdumpという関数が使えるようになりますので、こちらを使って表示してみます。

  • Controllerでの使用方法
    dump($app)

  • Twigでの使用方法
    {{ dump(app) }}

Application {#8 ▼
  #providers: array:21 [▼
    0 => EccubeMonologServiceProvider {#34}
    1 => MonologServiceProvider {#35}
    2 => TranslationServiceProvider {#46}
    3 => SessionServiceProvider {#55 ▶}
    4 => TwigServiceProvider {#59}
    5 => HttpFragmentServiceProvider {#84}
    6 => UrlGeneratorServiceProvider {#99}
    7 => FormServiceProvider {#102}
    8 => SerializerServiceProvider {#119}
    9 => ValidatorServiceProvider {#126}
    10 => SwiftmailerServiceProvider {#140}
    11 => DoctrineServiceProvider {#155}
    12 => DoctrineOrmManagerRegistryProvider {#170}
    13 => DoctrineOrmServiceProvider {#194}
    14 => SecurityServiceProvider {#171 ▶}
    15 => RememberMeServiceProvider {#188}
    16 => EccubeServiceProvider {#259}
    17 => ServiceControllerServiceProvider {#585}
    18 => WebProfilerServiceProvider {#1068}
    19 => DebugServiceProvider {#1134}
    20 => SaxulumWebProfilerProvider {#1147}
  ]
  #booted: true
  #values: array:318 [▼
    "logger" => Closure {#36 ▶}
    "routes" => Closure {#9 ▶}
    "controllers" => Closure {#11 ▶}
    "controllers_factory" => Closure {#12 ▶}
    "route_class" => "Silex\Route"
    "route_factory" => Closure {#13 ▶}
    "exception_handler" => Closure {#15 ▶}
    "dispatcher_class" => "Symfony\Component\EventDispatcher\EventDispatcher"
    "dispatcher" => Closure {#1186 ▶}
    "callback_resolver" => Closure {#19 ▶}
    "resolver" => Closure {#588 ▶}
    "kernel" => Closure {#23 ▶}
    "request_stack" => Closure {#25 ▶}
    "request_context" => Closure {#27 ▶}
    "url_matcher" => Closure {#29 ▶}
    "request_error" => Closure {#31 ▶}
    "request" => Request {#1139 ▶}
    "request.http_port" => 80
    "request.https_port" => 443
    "debug" => true
    "charset" => "UTF-8"
    "locale" => "ja"
    "config" => Closure {#1026 ▶}
    "monolog.handler.debug" => Closure {#38 ▶}
    "monolog.logger.class" => "Symfony\Bridge\Monolog\Logger"
    "monolog" => Closure {#39 ▶}
    "monolog.handler" => Closure {#44 ▶}
    "monolog.level" => Closure {#41 ▶}
    "monolog.listener" => Closure {#43 ▶}
    "monolog.name" => "myapp"
    "monolog.bubble" => true
    "monolog.permission" => null
    "listener.requestdump" => Closure {#45 ▶}
    "monolog.logfile" => "/XXXX/XXXX/ECCUBEROOT/src/Eccube/../../app/log/site.log"
    "translator" => Closure {#54 ▶}
    "translator.resources" => Closure {#50 ▶}
    "translator.message_selector" => Closure {#52 ▶}
    "translator.domains" => []
    "locale_fallbacks" => array:1 [▶]
    "translator.cache_dir" => null
    "session.test" => false
    "session" => Closure {#57 ▶}
    "session.storage.handler" => Closure {#64 ▶}
    "session.storage.native" => Closure {#61 ▶}
    "session.storage.test" => Closure {#63 ▶}
    "session.storage.options" => array:5 [▶]
    "session.default_locale" => "en"
    "session.storage.save_path" => null
    "session.db_options" => array:1 [▶]
    "twig.options" => array:3 [▶]
    "twig.form.templates" => array:1 [▶]
    "twig.path" => []
    "twig.templates" => []
    "twig" => Closure {#658 ▶}
    "twig.loader.filesystem" => Closure {#1153 ▶}
    "twig.loader.array" => Closure {#69 ▶}
    "twig.loader" => Closure {#71 ▶}
    "fragment.handler" => Closure {#86 ▶}
    "fragment.renderer.inline" => Closure {#88 ▶}
    "fragment.renderer.hinclude" => Closure {#90 ▶}
    "fragment.renderer.esi" => Closure {#92 ▶}
    "fragment.listener" => Closure {#94 ▶}
    "uri_signer" => Closure {#96 ▶}
    "uri_signer.secret" => "e777a79cd661dbad23978972d11ee82d"
    "fragment.path" => "/_fragment"
    "fragment.renderer.hinclude.global_template" => null
    "fragment.renderers" => Closure {#98 ▶}
    "url_generator" => Closure {#101 ▶}
    "form.secret" => "e777a79cd661dbad23978972d11ee82d"
    "form.types" => Closure {#584 ▶}
    "form.type.extensions" => Closure {#1113 ▶}
    "form.type.guessers" => Closure {#108 ▶}
    "form.extension.csrf" => Closure {#110 ▶}
    "form.extensions" => Closure {#176 ▶}
    "form.factory" => Closure {#114 ▶}
    "form.resolved_type_factory" => Closure {#1082 ▶}
    "form.csrf_provider" => Closure {#118 ▶}
    "serializer" => Closure {#121 ▶}
    "serializer.encoders" => Closure {#123 ▶}
    "serializer.normalizers" => Closure {#125 ▶}
    "validator" => Closure {#128 ▶}
    "validator.mapping.class_metadata_factory" => Closure {#130 ▶}
    "validator.validator_factory" => Closure {#132 ▶}
    "validator.object_initializers" => Closure {#181 ▶}
    "swiftmailer.options" => array:7 [▶]
    "swiftmailer.use_spool" => true
    "mailer.initialized" => true
    "mailer" => Closure {#142 ▶}
    "swiftmailer.spooltransport" => Closure {#144 ▶}
    "swiftmailer.spool" => Closure {#146 ▶}
    "swiftmailer.transport" => Closure {#148 ▶}
    "swiftmailer.transport.buffer" => Closure {#150 ▶}
    "swiftmailer.transport.authhandler" => Closure {#152 ▶}
    "swiftmailer.transport.eventdispatcher" => Closure {#154 ▶}
    "db.default_options" => array:5 [▶]
    "dbs.options.initializer" => Closure {#157 ▶}
    "dbs" => Closure {#159 ▶}
    "dbs.config" => Closure {#161 ▶}
    "dbs.event_manager" => Closure {#163 ▶}
    "db" => Closure {#165 ▶}
    "db.config" => Closure {#167 ▶}
    "db.event_manager" => Closure {#169 ▶}
    "dbs.options" => array:2 [▶]
    "doctrine" => Closure {#173 ▶}
    "doctrine.orm.validator.unique_validator" => Closure {#177 ▶}
    "validator.validator_service_ids" => array:2 [▶]
    "orm.proxies_dir" => "/XXXX/XXXX/ECCUBEROOT/src/Eccube/../../app/cache/doctrine"
    "orm.proxies_namespace" => "DoctrineProxy"
    "orm.auto_generate_proxies" => true
    "orm.default_cache" => "array"
    "orm.custom.functions.string" => []
    "orm.custom.functions.numeric" => []
    "orm.custom.functions.datetime" => []
    "orm.custom.hydration_modes" => []
    "orm.class_metadata_factory_name" => "Doctrine\ORM\Mapping\ClassMetadataFactory"
    "orm.default_repository_class" => "Doctrine\ORM\EntityRepository"
    "orm.em.default_options" => array:3 [▶]
    "orm.ems.options.initializer" => Closure {#192 ▶}
    "orm.em_name_from_param_key" => Closure {#190 ▶}
    "orm.ems" => Closure {#196 ▶}
    "orm.ems.config" => Closure {#197 ▶}
    "orm.cache.configurer" => Closure {#199 ▶}
    "orm.cache.locator" => Closure {#201 ▶}
    "orm.cache.factory.backing_memcache" => Closure {#203 ▶}
    "orm.cache.factory.memcache" => Closure {#205 ▶}
    "orm.cache.factory.backing_memcached" => Closure {#207 ▶}
    "orm.cache.factory.memcached" => Closure {#209 ▶}
    "orm.cache.factory.backing_redis" => Closure {#211 ▶}
    "orm.cache.factory.redis" => Closure {#213 ▶}
    "orm.cache.factory.array" => Closure {#215 ▶}
    "orm.cache.factory.apc" => Closure {#217 ▶}
    "orm.cache.factory.xcache" => Closure {#219 ▶}
    "orm.cache.factory.filesystem" => Closure {#221 ▶}
    "orm.cache.factory" => Closure {#223 ▶}
    "orm.mapping_driver_chain.locator" => Closure {#225 ▶}
    "orm.mapping_driver_chain.factory" => Closure {#227 ▶}
    "orm.add_mapping_driver" => Closure {#229 ▶}
    "orm.generate_psr0_mapping" => Closure {#231 ▶}
    "orm.strategy.naming" => Closure {#233 ▶}
    "orm.strategy.quote" => Closure {#235 ▶}
    "orm.entity_listener_resolver" => Closure {#237 ▶}
    "orm.repository_factory" => Closure {#239 ▶}
    "orm.em" => Closure {#578 ▶}
    "orm.em.config" => Closure {#243 ▶}
    "orm.em.options" => array:1 [▶]
    "security.role_hierarchy" => []
    "security.access_rules" => array:6 [▶]
    "security.hide_user_not_found" => true
    "security.authorization_checker" => Closure {#244 ▶}
    "security.token_storage" => Closure {#246 ▶}
    "security" => Closure {#248 ▶}
    "user" => Closure {#448 ▶}
    "security.authentication_manager" => Closure {#251 ▶}
    "security.encoder_factory" => Closure {#446 ▶}
    "security.encoder.digest" => Closure {#255 ▶}
    "security.user_checker" => Closure {#257 ▶}
    "security.access_manager" => Closure {#468 ▶}
    "security.voters" => Closure {#466 ▶}
    "security.firewall" => Closure {#263 ▶}
    "security.channel_listener" => Closure {#265 ▶}
    "security.authentication_listener.factory.logout" => Closure {#267 ▶}
    "security.authentication_listener.factory.pre_auth" => Closure {#269 ▶}
    "security.authentication_listener.factory.form" => Closure {#271 ▶}
    "security.authentication_listener.factory.http" => Closure {#273 ▶}
    "security.authentication_listener.factory.remember_me" => Closure {#184 ▶}
    "security.authentication_listener.factory.anonymous" => Closure {#277 ▶}
    "security.firewall_map" => Closure {#279 ▶}
    "security.access_listener" => Closure {#281 ▶}
    "security.access_map" => Closure {#283 ▶}
    "security.trust_resolver" => Closure {#285 ▶}
    "security.session_strategy" => Closure {#287 ▶}
    "security.http_utils" => Closure {#289 ▶}
    "security.last_error" => Closure {#291 ▶}
    "security.context_listener._proto" => Closure {#293 ▶}
    "security.user_provider.inmemory._proto" => Closure {#295 ▶}
    "security.exception_listener._proto" => Closure {#297 ▶}
    "security.authentication.success_handler._proto" => Closure {#299 ▶}
    "security.authentication.failure_handler._proto" => Closure {#301 ▶}
    "security.authentication_listener.form._proto" => Closure {#303 ▶}
    "security.authentication_listener.http._proto" => Closure {#305 ▶}
    "security.authentication_listener.anonymous._proto" => Closure {#307 ▶}
    "security.authentication.logout_handler._proto" => Closure {#309 ▶}
    "security.authentication_listener.logout._proto" => Closure {#311 ▶}
    "security.authentication_listener.switch_user._proto" => Closure {#313 ▶}
    "security.entry_point.form._proto" => Closure {#315 ▶}
    "security.entry_point.http._proto" => Closure {#317 ▶}
    "security.authentication_provider.dao._proto" => Closure {#319 ▶}
    "security.authentication_provider.anonymous._proto" => Closure {#321 ▶}
    "security.validator.user_password_validator" => Closure {#323 ▶}
    "security.remember_me.response_listener" => Closure {#183 ▶}
    "security.remember_me.service._proto" => Closure {#274 ▶}
    "security.authentication_listener.remember_me._proto" => Closure {#324 ▶}
    "security.authentication_provider.remember_me._proto" => Closure {#326 ▶}
    "orm.ems.options" => array:1 [▶]
    "orm.ems.default" => "default"
    "orm.cache.instances.default.metadata" => ArrayCache {#331 ▶}
    "orm.cache.instances.default.query" => ArrayCache {#329 ▶}
    "orm.cache.instances.default.result" => ArrayCache {#332 ▶}
    "orm.cache.instances.default.hydration" => ArrayCache {#333 ▶}
    "orm.mapping_driver_chain.instances.default" => MappingDriverChain {#338 ▶}
    "dbs.default" => "default"
    "security.firewalls" => array:2 [▶]
    "eccube.password_encoder" => Closure {#444 ▶}
    "eccube.event_listner.security" => Closure {#252 ▶}
    "authority_voter" => Closure {#464 ▶}
    "eccube.service.system" => Closure {#469 ▶}
    "view" => Closure {#471 ▶}
    "eccube.service.cart" => Closure {#473 ▶}
    "eccube.service.order" => Closure {#475 ▶}
    "eccube.service.tax_rule" => Closure {#477 ▶}
    "eccube.service.plugin" => Closure {#479 ▶}
    "eccube.service.mail" => Closure {#481 ▶}
    "eccube.service.csv.export" => Closure {#483 ▶}
    "eccube.service.shopping" => Closure {#485 ▶}
    "eccube.repository.master.authority" => Closure {#487 ▶}
    "eccube.repository.master.tag" => Closure {#489 ▶}
    "eccube.repository.master.pref" => Closure {#491 ▶}
    "eccube.repository.master.sex" => Closure {#493 ▶}
    "eccube.repository.master.disp" => Closure {#495 ▶}
    "eccube.repository.master.product_type" => Closure {#497 ▶}
    "eccube.repository.master.page_max" => Closure {#499 ▶}
    "eccube.repository.master.order_status" => Closure {#501 ▶}
    "eccube.repository.master.device_type" => Closure {#503 ▶}
    "eccube.repository.master.csv_type" => Closure {#505 ▶}
    "eccube.repository.delivery" => Closure {#507 ▶}
    "eccube.repository.delivery_date" => Closure {#509 ▶}
    "eccube.repository.delivery_fee" => Closure {#511 ▶}
    "eccube.repository.delivery_time" => Closure {#513 ▶}
    "eccube.repository.payment" => Closure {#515 ▶}
    "eccube.repository.payment_option" => Closure {#517 ▶}
    "eccube.repository.category" => Closure {#519 ▶}
    "eccube.repository.customer" => Closure {#521 ▶}
    "eccube.repository.news" => Closure {#523 ▶}
    "eccube.repository.mail_history" => Closure {#525 ▶}
    "eccube.repository.member" => Closure {#527 ▶}
    "eccube.repository.order" => Closure {#553 ▶}
    "eccube.repository.product" => Closure {#531 ▶}
    "eccube.repository.product_image" => Closure {#533 ▶}
    "eccube.repository.product_class" => Closure {#535 ▶}
    "eccube.repository.product_stock" => Closure {#537 ▶}
    "eccube.repository.class_name" => Closure {#539 ▶}
    "eccube.repository.class_category" => Closure {#541 ▶}
    "eccube.repository.customer_favorite_product" => Closure {#543 ▶}
    "eccube.repository.base_info" => Closure {#545 ▶}
    "eccube.repository.tax_rule" => Closure {#547 ▶}
    "eccube.repository.page_layout" => Closure {#549 ▶}
    "eccube.repository.block" => Closure {#551 ▶}
    "eccube.repository.customer_address" => Closure {#528 ▶}
    "eccube.repository.shipping" => Closure {#555 ▶}
    "eccube.repository.customer_status" => Closure {#557 ▶}
    "eccube.repository.order_status" => Closure {#559 ▶}
    "eccube.repository.mail_template" => Closure {#561 ▶}
    "eccube.repository.csv" => Closure {#563 ▶}
    "eccube.repository.template" => Closure {#565 ▶}
    "eccube.repository.authority_role" => Closure {#567 ▶}
    "paginator" => Closure {#569 ▶}
    "eccube.repository.help" => Closure {#571 ▶}
    "eccube.repository.plugin" => Closure {#573 ▶}
    "eccube.repository.plugin_event_handler" => Closure {#575 ▶}
    "eccube.event.dispatcher" => Closure {#993 ▶}
    "profiler.mount_prefix" => "/_profiler"
    "data_collector.templates" => array:12 [▶]
    "data_collectors" => array:12 [▶]
    "data_collectors.form.extractor" => Closure {#1065 ▶}
    "twig.profiler.profile" => Closure {#1110 ▶}
    "web_profiler.controller.profiler" => Closure {#1104 ▶}
    "web_profiler.controller.router" => Closure {#1100 ▶}
    "web_profiler.controller.exception" => Closure {#1081 ▶}
    "web_profiler.toolbar.listener" => Closure {#1084 ▶}
    "profiler" => Closure {#1120 ▶}
    "profiler.storage" => Closure {#1122 ▶}
    "profiler.request_matcher" => null
    "profiler.only_exceptions" => false
    "profiler.only_master_requests" => false
    "web_profiler.debug_toolbar.enable" => true
    "web_profiler.debug_toolbar.position" => "bottom"
    "web_profiler.debug_toolbar.intercept_redirects" => false
    "profiler.listener" => Closure {#1124 ▶}
    "stopwatch" => Closure {#1126 ▶}
    "code.file_link_format" => null
    "profiler.templates_path" => Closure {#1133 ▶}
    "profiler.cache_dir" => "/XXXX/XXXX/ECCUBEROOT/html/../app/cache/profiler"
    "var_dumper.cloner" => Closure {#1136 ▶}
    "data_collector.dump" => Closure {#1071 ▶}
    "debug.templates_path" => Closure {#1146 ▶}
    "debug.max_items" => -1
    "debug.max_string_length" => -1
    "security.user_provider.admin" => MemberRepository {#397 ▶}
    "security.context_listener.admin" => Closure {#1189 ▶}
    "security.entry_point.admin.form" => Closure {#1191 ▶}
    "security.authentication_listener.admin.form" => Closure {#1193 ▶}
    "security.authentication_provider.admin.dao" => Closure {#1195 ▶}
    "security.authentication_listener.admin.logout" => Closure {#1197 ▶}
    "security.authentication_listener.admin.anonymous" => Closure {#1199 ▶}
    "security.authentication_provider.admin.anonymous" => Closure {#1201 ▶}
    "security.exception_listener.admin" => Closure {#1203 ▶}
    "security.user_provider.customer" => CustomerRepository {#443 ▶}
    "security.context_listener.customer" => Closure {#1205 ▶}
    "security.entry_point.customer.form" => Closure {#1207 ▶}
    "security.authentication_listener.customer.form" => Closure {#1209 ▶}
    "security.authentication_provider.customer.dao" => Closure {#1211 ▶}
    "security.authentication_listener.customer.logout" => Closure {#1213 ▶}
    "security.remember_me.service.customer" => Closure {#1215 ▶}
    "security.authentication_listener.customer.remember_me" => Closure {#1217 ▶}
    "security.authentication_provider.customer.remember_me" => Closure {#1219 ▶}
    "security.authentication_listener.customer.anonymous" => Closure {#1221 ▶}
    "security.authentication_provider.customer.anonymous" => Closure {#1223 ▶}
    "security.exception_listener.customer" => Closure {#1225 ▶}
    "security.authentication_providers" => array:5 [▶]
    "security.authentication.logout_handler.admin" => Closure {#1249 ▶}
    "security.authentication.success_handler.admin" => Closure {#591 ▶}
    "security.authentication.failure_handler.admin" => Closure {#992 ▶}
    "session.storage" => NativeSessionStorage {#980 ▶}
    "security.authentication.logout_handler.customer" => Closure {#922 ▶}
    "security.authentication.success_handler.customer" => Closure {#910 ▶}
    "security.authentication.failure_handler.customer" => Closure {#906 ▶}
    "twig.form.engine" => Closure {#766 ▶}
    "twig.form.renderer" => Closure {#762 ▶}
  ]
}

Application.phpでDIでセットしたものが格納されています。 そのため、$app['orm.em]とするとEntityManagerなどが呼び出されるわけです。

最初はとまどうかもしれませんが、こちらはこういうものだと覚えておいてください。

EC-CUBE3をさくらのレンタルサーバにインストールした時にhtmlを付けさせない方法

過去の記事ではURLに/htmlを付けさせない方法を書いてきました。

EC-CUBE3のURL設定について - AmidaikeBlog

EC-CUBE3のURL設定について2 - AmidaikeBlog

レンタルサーバでEC-CUBE3でのURL設定の仕方について - AmidaikeBlog

レンタルサーバでEC-CUBE3のURLにhtmlを付けさせない方法 - AmidaikeBlog

今回はさくらのレンタルサーバに特化してしまいますが、以下の通りにすればhtmlを無くす事ができます。

クイックインストールを使うのでEC-CUBE3をアップロードをしてインストールされる方は勝手が異なりますのでご注意ください。

今回の方法では、初期ドメイン(sakura.ne.jp)でインストールした後に独自ドメインを割り当てる方法となります。

1.クイックインストール時に初期ドメイン(xxxxxx.sakura.ne.jp)でインストールを行います。その際、ec-cubeをインストールするディレクトリを指定してください。

2.クイックインストールが完了しましたら、独自ドメインの指定ディレクトリを先ほどec-cubeをインストールしたディレクトリに設定します。

3.EC-CUBEをインストールしたディレクトリの配下にある/htmlディレクトリの.htaccessを以下のように変更を行います。

RewriteBase /html

4.さらに、EC-CUBEをインストールしたディレクトリ直下と/app配下の.htaccessを以下の様に修正します。

<FilesMatch "^composer|^autoload|^cli-config|^COPYING|\.(ht|ini|lock|dist|git|sh)$">
     order allow,deny
     deny from all
</FilesMatch>

<Files ~ "index.php|index_dev.php">
     order deny,allow
     allow from all
</Files>

<IfModule mod_rewrite.c>
     RewriteEngine On
     RewriteBase /html/

     RewriteRule ^user_data/(.*)$ /html/user_data/$1 [QSA,L]

     RewriteCond %{REQUEST_FILENAME} !-f
     RewriteCond %{REQUEST_FILENAME} !^(.*)\.(gif|png|jpg|css|ico|js)$ [NC]
     RewriteRule ^(.*)$ index.php [QSA,L]

</IfModule>

5.http://独自ドメイン/htmlでEC-CUBEインストーラーが 表示されますので通常のインストールを行ってください。

6.インストールが完了すれば、 app/config/eccube/にファイルが作成されますので、 ファイルマネージャーなどを利用してapp/config/eccube/path.ymlの以下の部分を修正します。

root_urlpath : /html/
↓
root_urlpath :

7.以上の設定で、htmlをなくしてサイトが表示されます。

8.新規ページを作成する場合、以下のカスタマイズを行う必要がありますので必要な方は修正をしてください。

html/index.php
のif文の内容を下記の該当する部分のように変更してください。

// インストールされてなければインストーラにリダイレクト
if ($app['config']['eccube_install']) {
    $app->initialize();
    $app->initializePlugin();

    $front = $app['controllers_factory'];
    // 強制SSL
    if ($app['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) {
        $front->requireHttps();
    }

    $front->match('/{route}', '\Eccube\Controller\UserDataController::index')->assert('route', '([0-9a-zA-Z_\-]+\/?)+(?<!\/)')->bind('user_data');
    $app->mount('', $front);

    if ($app['config']['http_cache']['enabled']) {
        $app['http_cache']->run();
    } else {
        $app->run();
    }
} else {
    $location = str_replace('index.php', 'install.php', $_SERVER['SCRIPT_NAME']);
    header('Location:'.$location);
    exit;
}

src/Eccube/ControllerProvider/FrontControllerProvider.php

// user定義
$c->match('/'.$app['config']['user_data_route'].'/{route}', '\Eccube\Controller\UserDataController::index')->assert('route', '([0-9a-zA-Z_\-]+\/?)+(?<!\/)')->bind('user_data');

// user定義
// $c->match('/'.$app['config']['user_data_route'].'/{route}', '\Eccube\Controller\UserDataController::index')->assert('route', '([0-9a-zA-Z_\-]+\/?)+(?<!\/)')->bind('user_data');

コメントアウトしてください。

今回はさくらのレンタルサーバを対象に記述しましたが、他のレンタルサーバでも同様に動くかもしれませんので是非お試しください。

【 2016/09/29 追記】

EC-CUBE3.0.11よりhtmlを削除する機能が提供されました。

amidaike.hatenablog.com

EC-CUBE3のプラグインのフックポイントについて

EC-CUBE Advent Calendar 2015 4日目の記事です。

4日目はEC-CUBE3でブラグインを実行する際に定義されているフックポイントについてです。

皆さんEC-CUBE3のプラグインを作っていますか?

プラグインの開発に慣れていくに従って段々と疑問に思ってくるのがフックポイントについてです。

勉強会などを行うときに必ず聞かれる内容として 「各フックポイントの実行タイミングが良く分からない」と尋ねられます。

今回は簡単に各フックポイントについてまとめました。

フックポイントを説明する前に先ずはSymfony2では標準で

  • kernel.request
  • kernel.controller
  • kernel.view
  • kernel.response
  • kernel.exception

というイベントが存在しています。

詳しくはこちら。 The HttpKernel Component (The Symfony Components)

EC-CUBE3ではSymfony2のイベント

  • kernel.request
  • kernel.response
  • kernel.terminate

の各イベントに対して処理を挟み込めるフックポイントが用意されています。

詳しくはこちら。ミドルウェア (Middlewares) | Japan Symfony Group

EC-CUBE3で用意されているフックポイントについて *1

Middleware

  • アプリケーション全体の処理の前後・特定のページの処理の前後に 処理を介入させることができます。
  • 全てのControllerに対して介入が可能です。

FilterResponseEvent

  • Responseが返却される描画される直前のHTTP HeaderやBodyを 書き換えることができます。
  • HTMLだけでなく、JSONで返却したいなどの変更も可能です。

今までの説明だけではさっぱり分からないと思いますので、実際に動作をさせてみましょう。

今回はプラグインの作成方法について説明は割愛しますが、 こういうプラグインを作って用意されているフックポイントの実行タイミングを確認してみました。

  • config.yml
name: フックポイント確認プラグイン
code: HookPoint
version: 1.0.0
event: HookPointEvent
  • event.yml
eccube.event.app.before:
  - [onAppBefore, NORMAL]
eccube.event.app.after:
  - [onAppAfter, NORMAL]
eccube.event.controller.homepage.before:
  - [onControllerBefore, NORMAL]
eccube.event.controller.homepage.after:
  - [onControllerAfter, NORMAL]
eccube.event.controller.homepage.finish:
  - [onControllerFinish, NORMAL]
eccube.event.render.homepage.before:
  - [onRenderBefore, NORMAL]
  • HookPointEvent.php
<?php
namespace Plugin\HookPoint;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

class HookPointEvent
{

    /** @var  \Eccube\Application $app */
    private $app;

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

    public function onAppBefore()
    {
        error_log("onAppBefore");
    }

    public function onAppAfter()
    {
        error_log("onAppAfter");
    }

    public function onControllerBefore()
    {
        error_log("onControllerBefore");
    }

    public function onControllerAfter()
    {
        error_log("onControllerAfter");
    }

    public function onControllerFinish()
    {
        error_log("onControllerFinish");
    }

    public function onRenderBefore(FilterResponseEvent $event)
    {
        error_log("onRenderBefore");
    }
}
  • TopController.php
use Eccube\Application;

class TopController
{

    public function index(Application $app)
    {
        error_log('TopController::index')
        return $app->render('index.twig');
    }
}
  • ApplicationTrait.php(一部抜粋)
public function render($view, array $parameters = array(), Response $response = null)
{
    $twig = $this['twig'];

    if ($response instanceof StreamedResponse) {
        $response->setCallback(function () use ($twig, $view, $parameters) {
            $twig->display($view, $parameters);
        });
    } else {
        if (null === $response) {
            $response = new Response();
        }
        $response->setContent($twig->render($view, $parameters));
    }

    error_log("twig render");

    return $response;
}

これらを実行すると以下が出力されます。(実際にはもう少し出力されますが)

 onAppBefore
 onControllerBefore
 TopController::index
 twig render
 onControllerAfter
 onRenderBefore
 onAppAfter
 onControllerFinish

最初に実行されるのが

eccube.event.app.before

であとは大体想定通りと思いますが、意外だったのが

onControllerFinish

です。onAppAfterより後に実行されるのは想定外でしたが、この順番で実行されていきます。

では、それぞれのフックポイントのイベントについては何を記述すれば良いかというと、

フックポイント 処理の内容など Symfony2に対応するイベント
onAppBefore アプリケーション共通の前処理を記述 kernel.request (EARLY_EVENT)
onAppAfter アプリケーション共通の後処理を記述 kernel.request (LATE_EVENT)
onControllerBefore Controllerが実行される前に行う処理を記述 kernel.request
onControllerAfter Controllerが実行された後に行う処理を記述 kernel.response
onControllerFinish Controllerが最後まで実行された後に行う処理を記述 kernel.terminate
onRenderBefore Viewに対して項目の追加などを行う処理を記述 kernel.response

になります。

プラグインを作成していて画面の拡張や処理の拡張をする場合、どのイベントに対して記述すれば分からないときはこちらの表を参考にしてください。

この記事がフックポイントについての理解について手助けになれば幸いです。

EC-CUBEプラグインアワードの締め切りも近いので是非ご応募お待ちしております。 www.ec-cube.net

5日目は@tuyop1です。

EC-CUBE3.0.5以降でPostgres9の環境だと正常に動作しない時の対処方法

EC-CUBE3.0.5からsessionの保存方法としてDB(dtb_session)を使うことになりました。

ただ、MySQLだと正常に動作しますが、 Postgres9だと環境によっては正常に動作しない時があります。 →MacのHomebrewでインストールしたPostgres9など

原因はSymfony2の問題であり、まだSymfony2側では対応されておりません。

NativeSessionStorage->loadSession() empty $_SESSION with PdoSessionHandler and pgsql · Issue #14569 · symfony/symfony · GitHub

回避方法としては以下のSQLを実行すると動作されるようになります。

ALTER DATABASE データベース名 SET bytea_output = 'escape';

Postgres9以降で動作しないよーという方はぜひお試しください。

EC-CUBE3でMailgunを使ったメール送信方法

以前にEC-CUBE3からGmailを使ったメール送信方法を書きました。

amidaike.hatenablog.com

今回はMailgunを使ったメール送信方法について説明します。

www.mailgun.com

Mailgunの説明は今回割愛しますが Mailgunの管理画面にあるDomain Informationの Default SMTP LoginDefault Password を設定することで簡単に送信できます。

app/config/eccube/mail.yml

mail:
    transport: smtp
    host: smtp.mailgun.org
    port: 25
    username: Mailgunで設定されているDefault SMTP Login
    password: Mailgunで設定されているDefault Password
    encryption: null
    auth_mode: null
    charset_iso_2022_jp: false

以上を設定するだけでメール送信が可能となります。

Mailgunは月10,000通までは無料なので、 クラウドVPSEC-CUBEの環境は出来たけどメールサーバまで作るのはしんどいという方にはお手軽に扱えるサービスです。

今回はSMTPを使ってメール送信の仕方を説明しましたが、 MailgunはAPIが提供されており本来であれば色々とできますので、 もっと色々と細かいことをしたい方はプラグインを作成してみてはいかがでしょうか。

EC-CUBE2とEC-CUBE3のテーブル比較

EC-CUBE3のテーブルについてEC-CUBE2からどのテーブルが無くなったりしているのか把握していなかったので、簡単に比較表を作成してまとめてみました。

こんな感じです。

2系テーブル 論理テーブル名 3系テーブル
dtb_api_account APIアカウント ×
dtb_api_config API設定 ×
dtb_baseinfo 店基本情報 dtb_base_info
dtb_best_products おすすめ商品情報 ×
dtb_bkup バックアップ ×
dtb_bloc ブロック情報 dtb_block
dtb_blocposition ブロック記事情報 dtb_block_position
dtb_category カテゴリ情報 dtb_category
dtb_category_count カテゴリ商品数情報 dtb_category_count
dtb_category_total_count カテゴリ商品合計数情報 dtb_category_total_count
dtb_class 規格情報 dtb_class_name
dtb_classcategory 規格分類情報 dtb_class_category
dtb_csv CSV情報 dtb_csv
dtb_csv_sql CSV詳細設定SQL情報 ×
dtb_customer 顧客情報 dtb_customer
dtb_customer_favorite_products お気に入り商品情報 dtb_customer_favorite_product
dtb_deliv 配送業者情報 dtb_delivery
dtb_delivfee 送料情報 dtb_delivery_fee
dtb_delivtime 配送時間情報 dtb_delivery_time
dtb_holiday 休日情報 ×
dtb_index_list インデックス一覧 ×
dtb_kiyaku 規約情報 dtb_help
dtb_mail_history 受注メール送信履歴 dtb_mail_history
dtb_mailmaga_template メルマガテンプレート情報 ×
dtb_mailtemplate メールテンプレート情報 dtb_mail_template
dtb_maker メーカー ×
dtb_maker_count メーカーカウント ×
dtb_member 管理者情報 dtb_member
dtb_mobile_ext_session_id モバイルセッション情報 ×
dtb_module モジュール情報 ×
dtb_module_update_log モジュール更新ログ情報 ×
dtb_news 新着情報 dtb_news
dtb_order 受注情報 dtb_order
dtb_order_detail 受注詳細情報 dtb_order_detail
dtb_order_temp 受注一時情報 ×
dtb_other_deliv その他の配送先情報 dtb_customer_address
dtb_ownersstore_settings オーナーズストア設定 ×
dtb_pagelayout ページレイアウト情報 dtb_page_layout
dtb_payment 支払方法情報 dtb_payment
dtb_payment_options 支払選択肢情報 dtb_payment_option
dtb_plugin プラグイン情報 dtb_plugin
dtb_plugin_hookpoint プラグインフックポイント ×
dtb_products 商品情報 dtb_product
dtb_product_categories 商品カテゴリ関連 dtb_product_category
dtb_product_class 商品規格情報 dtb_product_class
dtb_product_status 商品ステータス情報 ×
dtb_recommend_products 関連商品情報 ×
dtb_review レビュー除法 ×
dtb_send_customer 顧客メール送信履歴 ×
dtb_send_history メール送信履歴 ×
dtb_session セッション情報 dtb_session
dtb_shipment_item 配送商品情報 dtb_shipment_item
dtb_shipping お届け先情報 dtb_shipping
dtb_tax_rule 消費税ルール dtb_tax_rule
dtb_templates テンプレート情報 dtb_template
dtb_update モジュール更新情報 ×
mtb_allowed_tag 許可タグ ×
mtb_auth_excludes 管理画面認証除外 ×
mtb_authority 管理者マスタ mtb_authority
mtb_constants 定数マスタ ×
mtb_country 国マスタ mtb_country
mtb_customer_order_status 顧客表示用受注ステータス mtb_cusotmer_order_status
mtb_customer_status 顧客ステータス mtb_customer_status
mtb_db データベース種別 mtb_db
mtb_delivery_date 商品発送日 dtb_delivery_date
mtb_device_type 端末種別 mtb_device_type
mtb_disable_logout ログアウト無効ページ ×
mtb_disp 公開フラグ mtb_disp
mtb_job 職業マスタ mtb_job
mtb_magazine_type メルマガ種別 ×
mtb_mail_magazine_type メールマガジン種別 ×
mtb_mail_template メールテンプレート ×
mtb_mail_tpl_path メールテンプレートパス ×
mtb_mail_type メール種別 ×
mtb_mobile_domain モバイルドメイン ×
mtb_order_status 受注状態 mtb_order_status
mtb_order_status_color 受注ステータス色 mtb_order_status_color
mtb_ownersstoer_err オーナーズストアエラー種別 ×
mtb_page_max ページ最大表示数 mtb_page_max
mtb_permission 管理画面アクセス権限 ×
mtb_pref 都道府県マスタ mtb_pref
mtb_product_list_max 商品一覧最大表示数 mtb_product_list_max
mtb_product_status_color 商品ステータス色 ×
mtb_product_type 商品種別マスタ mtb_product_type
mtb_recommend おすすめレベル ×
mtb_reminder パスワード質問マスタ ×
mtb_review_deny_url レビュー拒否URL ×
mtb_sex 性別マスタ mtb_sex
mtb_status 商品ステータス ×
mtb_status_image ステータス画像 ×
mtb_target ブロックターゲット ×
mtb_taxrule 課税規則マスタ mtb_taxrule
mtb_wday 曜日 ×
mtb_work 管理者稼働状態 mtb_work
mtb_zip 郵便番号 mtb_zip

こうしてまとめてみると、結構テーブルが無くなっていますね。 機能自体がなくなっているものもあるため、致し方ありませんが。 2系から3系へ頑張って移行されようとしている方はこちらを参考に頑張ってください。

レンタルサーバでEC-CUBE3のURLにhtmlを付けさせない方法

以前にEC-CUBE3をレンタルサーバにインストールする際のURLの設定の仕方について以下の記事を書きました。

amidaike.hatenablog.com

通常ec-cubeをそのままインストールすると http://hogehoge.com/html/ とhtmlがurlについてしまいます。

その回避方法として上記記事を作成したのですが、 この記事内ではファイルを移動したりと結構面倒なことをしていたため、 .htaccessを使って対処できないかなと思い、 .htaccessを以下のようにごにょごにょと対応してみました。

ec-cube直下の.htaccessに現状

order allow,deny
deny from all

と記述されている内容を

<FilesMatch "^composer|^autoload|^cli-config|^COPYING|\.(ht|ini|lock|dist|git|sh)$">
    order allow,deny
    deny from all
</FilesMatch>

<Files ~ "index.php|index_dev.php">
    order deny,allow
    allow from all
</Files>

<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine On
    RewriteBase /html/

    RewriteRule ^user_data/(.*)$ /html/user_data/$1 [QSA,L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !^(.*)\.(gif|png|jpg|css|ico|js)$ [NC]
    RewriteRule ^(.*)$ index.php [QSA,L]

</IfModule>

に変更します。 その後、

app/config/eccube/path.yml

にあるroot_urlpath を

root_urlpath:

に修正すればhtmlがなくてもhttp://hogehoge.comだけでアクセス出来るようになります。

これで問題なく動作できるかどうか試していただけると助かります。 こちらはApache2.4未満の方を対象にしていますので、Apache2.4以上またはApache以外をお使いの方は別途対応できればと思います。

ただしこちらの対処だけではまだ不充分であり、 srcディレクトリやtestディレクトリvendorディレクトリなどの直下に対して、 appディレクトリ直下に置いてある.htaccessと同じものを置いて制限をかける必要があります。

【追記】
さくらサーバだとOptions +FollowSymlinksが使えないため、Optionsの行を消して対応可能かどうか試して頂ければと思います。