Magento Advent Calender 2017 の9日目の記事です。
ユーザが自分のアバター(画像アイコン)を登録できるモジュールを作成したいと思います。
- この記事から習得できる技術
-
- テーブルへの属性追加
- 画像の追加方法
- 全体的なイメージ
-
- カラムをcustomerテーブルに追加する
- 画像をバックエンドから追加、表示
- 画像をフロントエンドから追加、表示
カラムをcustomerテーブルに追加する
まず初めに、作成するモジュール名を決めてください。
今回は、Veriteworks_Avatarというモジュール名で作成したいと思います。
Veriteworks\Avatar\etc\module.xml
<sequence>タグでは、Magento_Catalogモジュールを読み込んでいます。
このAvatarモジュールが処理をする前に、読み込んでおきたいモジュールがあれば、<sequence>タグを使って読み込みましょう。
Veriteworks\Avatar\registration.php
MODULEにはmodule.xmlで定義したモジュール名を入れてください。
```php:registration.php \Magento\Framework\Component\ComponentRegistrar::register(\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Veriteworks_Avatar',
DIR
);
<h3>Veriteworks\Avatar\etc\frontend\routes.xml<br>
Veriteworks\Avatar\etc\adminhtml\routes.xml</h3>
<p>URLのルーティングに関する処理を行います。</p>
```xml:frontend/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="viewfile" frontName="viewfile">
<module name="Veriteworks_Avatar" />
</route>
</router>
</config>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
<route id="adminhtml">
<module name="Veriteworks_Avatar" before="Magento_Backend" />
</route>
<route id="avatar" frontName="avatar">
<module name="Veriteworks_Avatar" />
</route>
</router>
</config>
Veriteworks\Avatar\etc\adminhtml\system.xml
ここで、設定ページで設定する項目を作成することができます。
今回は、アバターモジュールの画像を表示するかしないかのプルダウンを作成しています。
次に、customer_entityテーブルにアバター画像の情報を属性として追加したいと思います。
Veriteworks\Avatar\Setup\InstallData.php
attributesInfoで、その属性の型を設定することができます。
57-60行目で、管理画面の顧客グリッドでアバター画像を表示するための設定をしています。
75行目では、サイト上のどのページでこの属性を使用できるようにするかの設定をしています。
use Magento\Customer\Model\Customer;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
/**
-
@codeCoverageIgnore
/
class InstallData implements InstallDataInterface
{
/*- Customer setup factory
-
@var CustomerSetupFactory
/
private $customerSetupFactory;
/* -
@var AttributeSetFactory
/
private $attributeSetFactory;
/* - Init
-
@param CustomerSetupFactory $customerSetupFactory
*/
public function __construct(
CustomerSetupFactory $customerSetupFactory,
AttributeSetFactory $attributeSetFactory
) {
$this->customerSetupFactory = $customerSetupFactory;
$this->attributeSetFactory = $attributeSetFactory;
}
/**
- @param ModuleDataSetupInterface $setup
-
@param ModuleContextInterface $context
/
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
/* @var CustomerSetup $customerSetup /
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$attributesInfo = [
'vwp_avatar' => [
'label' => 'Avatar',
'type' => 'varchar',
'input' => 'image',
'position' => 1000,
'visible' => true,
'required' => false,
'system' => 0,
'user_defined' => true,
'is_used_in_grid' => true,
'is_visible_in_grid' => true,
'is_html_allowed_on_front' => true,
'visible_on_front' => true,
]
];
$customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
/* @var $attributeSet AttributeSet */
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
foreach ($attributesInfo as $attributeCode => $attributeParams) {
$customerSetup->addAttribute(Customer::ENTITY, $attributeCode, $attributeParams);
}
$magentoUsernameAttribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'vwp_avatar');
$magentoUsernameAttribute->addData([
'attribute_set_id' => $attributeSetId,
'attribute_group_id' => $attributeGroupId,
'used_in_forms' => ['customer_account_create', 'customer_account_edit', 'adminhtml_customer'],
]);
$magentoUsernameAttribute->save();
$setup->endSetup();
}
}
<h2>画像をバックエンドから追加、表示</h2>
<p>次に実際に画像をアップロードし、ちゃんとテーブルに保存されるか確認したいと思います。<br>
管理画面から顧客情報を確認してみてください。</p>
<img width="144" alt="スクリーンショット 2017-11-30 11.14.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/119742/671e9c48-35eb-2bfc-0b0a-915b4f86b2bb.png"><p>まずグリッドにアバターの列が表示されているのがわかります。
そして、アカウント情報編集では、アバター画像がアップロードできるようボタンが追加されていると思います。</p>
<img width="1130" alt="スクリーンショット 2017-11-30 11.11.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/119742/52fc2444-cc31-b420-8e47-a469dd55282d.png"><br>
<p>アバター画像を保存すると、画像パスだけがグリッドに表示されるため、画像を表示するよう変更します。</p>
<h3>Veriteworks\Avatar\view\adminhtml\ui_component\customer_listing.xml</h3>
```xml:customer_listing.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<columns name="customer_columns" class="Magento\Customer\Ui\Component\Listing\Columns">
<column name="vwp_avatar" class="Veriteworks\Avatar\Ui\Component\Listing\Columns\Avatar">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/thumbnail</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="has_preview" xsi:type="string">1</item>
<item name="label" xsi:type="string" translate="true">Avatar</item>
<item name="sortOrder" xsi:type="number">1</item>
</item>
</argument>
</column>
</columns>
</listing>
Veriteworks\Avatar\Ui\Component\Listing\Columns\Avatar.php
```php:Avatar.php namespace Veriteworks\Avatar\Ui\Component\Listing\Columns;use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Framework\View\Element\UiComponent\ContextInterface;
/**
- Class Avatar
-
@package Veriteworks\Avatar\Ui\Component\Listing\Columns
/
class Avatar extends \Magento\Ui\Component\Listing\Columns\Column
{
/*-
@var \Magento\Framework\View\Element\AbstractBlock
/
protected $viewFileUrl;
/* - @param ContextInterface $context
- @param UiComponentFactory $uiComponentFactory
- @param \Magento\Catalog\Helper\Image $imageHelper
- @param \Magento\Framework\UrlInterface $urlBuilder
- @param array $components
-
@param array $data
/
public function __construct(
ContextInterface $context,
UiComponentFactory $uiComponentFactory,
\Magento\Framework\UrlInterface $urlBuilder,
\Magento\Framework\View\Asset\Repository $viewFileUrl,
array $components = [],
array $data = []
) {
parent::__construct($context, $uiComponentFactory, $components, $data);
$this->urlBuilder = $urlBuilder;
$this->viewFileUrl = $viewFileUrl;
}
/* - Prepare Data Source
- @param array $dataSource
-
@return array
*/
public function prepareDataSource(array $dataSource)
{
if (isset($dataSource['data']['items'])) {
$fieldName = $this->getData('name');
foreach ($dataSource['data']['items'] as & $item) {
$customer = new \Magento\Framework\DataObject($item);
$picture_url = !empty($customer["vwp_avatar"]) ? $this->urlBuilder->getUrl(
'customer/index/viewfile/image/'.base64_encode($customer["vwp_avatar"])) : $this->viewFileUrl->getUrl('Veriteworks_Avatar::images/no-profile-img.png');
$item[$fieldName . '_src'] = $picture_url;
$item[$fieldName . '_orig_src'] = $picture_url;
$item[$fieldName . '_alt'] = 'The profile picture';
}
}
return $dataSource;
}
}
-
@var \Magento\Framework\View\Element\AbstractBlock
<p>画像がまだ保存されていない顧客のために、デフォルトのアバター画像を表示するよう設定をしています。<br>
画像は<br>
Veriteworks\Avatar\view\adminhtml\web\images<br>
Veriteworks\Avatar\view\frontend\web\images<br>
に追加しておきましょう。</p>
<img width="90" alt="スクリーンショット 2017-12-06 11.23.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/119742/00b9524a-2d80-0fc3-dc3f-1e92cc523790.png"><br>
<p>画像が表示、追加されているのがわかると思います。</p>
<h2>画像をフロントエンドから追加、表示</h2>
<p>次に画像をフロントエンドから追加し、表示したいと思います。</p>
<h3>Veriteworks\Avatar\view\frontend\layout\customer_account_edit.xml</h3>
<p>アカウント情報ページから画像を追加するので、このファイルを追加します。</p>
```xml:customer_account_edit.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="form.additional.info">
<block class="Veriteworks\Avatar\Block\Form\ChangeAvatar" name="vwp_avatar_form_edit" template="form/changeAvatar.phtml"/>
</referenceContainer>
</body>
</page>
Veriteworks\Avatar\view\frontend\templates\changeAvatar.phtml
```php:changeAvatar.phtml```
Veriteworks\Avatar\Controller\Avatar\View.php
```php:view.php namespace Veriteworks\Avatar\Controller\Avatar;use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Customer\Api\CustomerMetadataInterface;
use Magento\Framework\Exception\NotFoundException;
/**
-
Class View
-
@package Veriteworks\Avatar\Controller\Avatar
/
class View extends \Magento\Framework\App\Action\Action
{
/*-
@var \Magento\Framework\Controller\Result\RawFactory
*/
protected $resultRawFactory;
/**
-
@var \Magento\Framework\Url\DecoderInterface
*/
protected $urlDecoder;
/**
-
@var \Magento\Framework\App\Response\Http\FileFactory
*/
protected $fileFactory;
/**
- @param \Magento\Framework\App\Action\Context $context
- @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
- @param \Magento\Framework\Url\DecoderInterface $urlDecoder
-
@param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\Controller\Result\RawFactory $resultRawFactory,
\Magento\Framework\Url\DecoderInterface $urlDecoder,
\Magento\Framework\App\Response\Http\FileFactory $fileFactory
) {
$this->resultRawFactory = $resultRawFactory;
$this->urlDecoder = $urlDecoder;
$this->fileFactory = $fileFactory;
return parent::__construct($context);
}
/**
-
View action
-
@return \Magento\Framework\View\Result\PageFactory
-
@SuppressWarnings(PHPMD.NPathComplexity)
*/
public function execute()
{
$file = null;
$plain = false;
if ($this->getRequest()->getParam('file')) {
// download file
$file = $this->urlDecoder->decode(
$this->getRequest()->getParam('file')
);
} elseif ($this->getRequest()->getParam('image')) {
// show plain image
$file = $this->urlDecoder->decode(
$this->getRequest()->getParam('image')
);
$plain = true;
} else {
throw new NotFoundException(__('Page not found.'));
}/** @var \Magento\Framework\Filesystem $filesystem */
$filesystem = $this->_objectManager->get('Magento\Framework\Filesystem');
$directory = $filesystem->getDirectoryRead(DirectoryList::MEDIA);
$fileName = CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . ltrim($file, '/');
$path = $directory->getAbsolutePath($fileName);if (!$directory->isFile($fileName)
&& !$this->_objectManager->get('Magento\MediaStorage\Helper\File\Storage')->processStorageFile($path)
) {
throw new NotFoundException(__('Page not found.'));
}if ($plain) {
$extension = pathinfo($path, PATHINFO_EXTENSION);
switch (strtolower($extension)) {
case 'gif':
$contentType = 'image/gif';
break;
case 'jpg':
$contentType = 'image/jpeg';
break;
case 'png':
$contentType = 'image/png';
break;
default:
$contentType = 'application/octet-stream';
break;
}
$stat = $directory->stat($fileName);
$contentLength = $stat['size'];
$contentModify = $stat['mtime'];/** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ $resultRaw = $this->resultRawFactory->create(); $resultRaw->setHttpResponseCode(200) ->setHeader('Pragma', 'public', true) ->setHeader('Content-type', $contentType, true) ->setHeader('Content-Length', $contentLength) ->setHeader('Last-Modified', date('r', $contentModify)); $resultRaw->setContents($directory->readFile($fileName)); return $resultRaw;
} else {
$name = pathinfo($path, PATHINFO_BASENAME);
$this->fileFactory->create(
$name,
['type' => 'filename', 'value' => $fileName],
DirectoryList::MEDIA
);
}
}
}
-
@var \Magento\Framework\Controller\Result\RawFactory
<h3>Veriteworks\Avatar\Block\Form\ChangeAvatar.php</h3>
```php:changeAvatar.phtml
<?php
namespace Veriteworks\Avatar\Block\Form;
use Magento\Customer\Api\AccountManagementInterface;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Customer\Api\CustomerMetadataInterface;
/**
* Class ChangeAvatar
* @package Veriteworks\Avatar\Block\Form
*/
class ChangeAvatar extends \Magento\Customer\Block\Form\Edit
{
/**
* @var \Magento\Newsletter\Model\Subscriber
*/
protected $subscription;
/**
* @var \Magento\Customer\Model\Session
*/
protected $customerSession;
/**
* @var \Magento\Newsletter\Model\SubscriberFactory
*/
protected $subscriberFactory;
/**
* @var CustomerRepositoryInterface
*/
protected $customerRepository;
/**
* @var AccountManagementInterface
*/
protected $customerAccountManagement;
/**
* @return string
*/
public function getImage()
{
$file = $this->customerSession->getCustomer()->getVwpAvatar();
if(is_null($file)) return $this->_assetRepo->getUrl('Veriteworks_Avatar::images/no-profile-img.png');
$directory = $this->_filesystem->getDirectoryRead(DirectoryList::MEDIA);
$fileName = CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . ltrim($file, '/');
$imageUrl = $directory->getAbsolutePath($fileName);
$currentStore = $this->_storeManager->getStore();
$mediaUrl = $currentStore->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$imagePath = $mediaUrl.$fileName;
return $this->getUrl('viewfile/avatar/view/', ['image' => base64_encode($file)]);
}
}
対応するテンプレートとブロックとコントローラを作成します。
画像が表示、追加できるのがわかると思います。
まとめ
今回の記事では、ユーザが自分のアバター(画像アイコン)を登録できるモジュールの作成方法について説明しました。
この記事から、テーブルへの属性追加と画像の追加方法が習得できます。
これを応用することで、例えばレビューやログイン画面などでユーザ名の横にアバターアイコンを表示することができます。