Magento 2: Как сгенерировать URL-ключ продукта при создании продукта из Rest API?
Я создаю продукт в magento usign Rest API. Используя следующий формат:
{
"product": {
"name": "Product Name",
"sku": "product_name_1498227094",
"attribute_set_id": "18",
"status": 1,
"visibility": 4,
"type_id": "simple",
"price": 0,
"weight": 0,
"product_links": [],
"options": [],
"tier_prices": [],
"custom_attributes": [
{
"attribute_code": "description",
"value": "Product About content"
},
{
"attribute_code": "short_description",
"value": "Product Mini content"
},
{
"attribute_code": "meta_title",
"value": "Product Name"
},
{
"attribute_code": "meta_keyword",
"value": "Product Name"
},
{
"attribute_code": "meta_description",
"value": "Product Name"
}
]
},
"saveOptions": true
}
Его продукт создается впервые. Но если я снова использую те же данные для создания продукта. Я получаю следующую ошибку:
[message] => URL key for specified store already exists.
Как вы можете проверить, я не передаю url_key
в массив custom_attributes
.
{
"attribute_code": "url_key",
"value": "10090-white-xl"
}
Вот мой вопрос: Не создает ли magento2 уникальный URL-ключ автоматически? Как мы можем сгенерировать уникальный URL-ключ в magento2 с учетом SEO?
5 answers
Я создал пользовательский код, чтобы проверить, существует ли URL-ключ или нет. В соответствии с потоком, используемым в функциях импорта продуктов в Magento 2.
public function __construct(
--
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\App\ResourceConnection $resource,
--
) {
--
$this->_storeManager = $storeManager;
$this->_resource = $resource;
--
}
public function createUrlKey($title, $sku)
{
$url = preg_replace('#[^0-9a-z]+#i', '-', $title);
$urlKey = strtolower($url);
$storeId = (int) $this->_storeManager->getStore()->getStoreId();
$isUnique = $this->checkUrlKeyDuplicates($sku, $urlKey, $storeId);
if ($isUnique) {
return $urlKey;
} else {
return $urlKey . '-' . time();
}
}
/*
* Function to check URL Key Duplicates in Database
*/
private function checkUrlKeyDuplicates($sku, $urlKey, $storeId)
{
$urlKey .= '.html';
$connection = $this->_resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
$tablename = $connection->getTableName('url_rewrite');
$sql = $connection->select()->from(
['url_rewrite' => $connection->getTableName('url_rewrite')], ['request_path', 'store_id']
)->joinLeft(
['cpe' => $connection->getTableName('catalog_product_entity')], "cpe.entity_id = url_rewrite.entity_id"
)->where('request_path IN (?)', $urlKey)
->where('store_id IN (?)', $storeId)
->where('cpe.sku not in (?)', $sku);
$urlKeyDuplicates = $connection->fetchAssoc($sql);
if (!empty($urlKeyDuplicates)) {
return false;
} else {
return true;
}
}
Для выполнения функции CreateUrlKey я добавил во вторую строку этот код:
$lastCharTitle = substr($title, -1);
$lastUrlChar = substr($url, -1);
if ($lastUrlChar == "-" && $lastCharTitle != "-"){
$url = substr($url, 0, strlen($url) - 1);
}
Чтобы удалить последний "-", если он сгенерирован из первой строки "preg_replace". Также я заменил метку времени уникальным артикулом, потому что иногда в процессе автоматического импорта время() двух соседних записей может быть одинаковым, поэтому оно не уникально.
Теперь функция такова:
public function createUrlKey($title, $sku)
{
$url = preg_replace('#[^0-9a-z]+#i', '-', $title);
$lastCharTitle = substr($title, -1);
$lastUrlChar = substr($url, -1);
if ($lastUrlChar == "-" && $lastCharTitle != "-"){
$url = substr($url, 0, strlen($url) - 1);
}
$urlKey = strtolower($url);
$storeId = (int) $this->_storeManager->getStore()->getStoreId();
$isUnique = $this->checkUrlKeyDuplicates($sku, $urlKey, $storeId);
if ($isUnique) {
return $urlKey;
} else {
return $urlKey . '-' . $sku;
}
}
Magento2 использует название продукта для автоматического создания URL-адреса. Поэтому, если у вас несколько продуктов с одинаковым названием, вы получите эту ошибку при попытке загрузить последующие продукты.
Мой совет состоял бы в том, чтобы либо отличать названия продуктов, поэтому, если у вас есть настраиваемый продукт с именем "КОРИЧНЕВАЯ РУБАШКА", вы бы загрузили простые продукты "КОРИЧНЕВАЯ РУБАШКА - S", "КОРИЧНЕВАЯ РУБАШКА - L" и т. Д.
В противном случае, если у вас могут быть продукты с одинаковым названием, вам нужно будет создать ваши собственные URL-ключи:
Возможно, добавьте артикул или что-то еще уникальное к названию продукта в ключе; например, "url_key": "sku001-коричневая рубашка" и т. Д.
Кто-нибудь уже сталкивался с проблемой в Magento 2.2, что у вас два разных названия продуктов, и magento создает один и тот же URL-ключ для обоих? Например:
Имя: Название продукта 1 url-ключ: название продукта-1
Название: Название продукта 2 url-ключ: название продукта-1
У меня сейчас такая проблема. Я публикую два разных продукта с разными названиями продуктов, а magento просто добавляет один продукт в магазин, и я задался вопросом, почему. Поэтому я взглянул на свой опубликованный контент и ответ от magento. И magento использует url-ключ из продукта 1 для продукта 2, хотя у меня есть две отдельные записи в api для этих двух продуктов. Не могу объяснить, почему magento делает это, и я не нашел никакого решения этой проблемы или проблемы/ошибки для Magento 2.2, но реализовал и опубликовал свой собственный URL-ключ. Я также удалил URL-ключи в базе данных url_rewrite.
Я уже добавил много продуктов в однотипный пост без каких-либо проблем.
Более эффективный способ - использовать коллекцию url_rewrite, как показано ниже, без использования диспетчера объектов:
$urlRewriteFactory = $this->_objectManager->create('\Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection');
$UrlRewriteCollectionData = $urlRewriteFactory->addFieldToFilter('request_path', ['eq' => $productUrlKey] )->addFieldToFilter('store_id', $this->scopeConfig->storeId);
$productUrlData = $UrlRewriteCollectionData->getFirstItem();
$existingProductUrlCount = 0;
if($productUrlData->getId()){
$existingProductUrlCount = 1;
}
try {
if ($existingProductUrlCount > 0){
return true;
}
} catch (\Exception $ex) {
$this->logInfo("Check for URL exists " . $ex->getMessage());
}
return false;