В Shopify метаполя полузащищены и не являются частью обычного продукта. Вы можете проверить это сами с помощью простого скрипта на странице продукта:
<script>
var product_info_from_liquid = {{ product | json }}
console.log('Product info from Liquid:',product_info_from_liquid)
</script>
Обратите внимание, что независимо от того, есть ли у продукта метаполя, в приведенном выше выводе метаполя не будет.
Аналогичным образом, если вы загружаете связанный с продуктом объект JSON из одной из конечных точек внешнего продукта, метаполя пропускаются. Чтобы проверить, мы можем проверить, взяв вывод JSON с обеих конечных точек внешнего интерфейса Shopify:
<script>
//Grabbing the data for the 'sleepy-head' product from the .js endpoint
jQuery.ajax({
url:'/products/sleepy-head.js',
dataType:'json',
success:function(product){
console.log('The ".js" results:', product)
}
//Grabbing the data for the 'sleepy-head' product from the .json endpoint
//I don't know why Shopify serves different at the .js and .json addresses, but apparently they do
jQuery.ajax({
url:'/products/sleepy-head.json',
dataType:'json',
success:function(product){
console.log('The ".json" results:', product)
}
})
</script>
Опять же, мы отмечаем, что независимо от того, каким образом мы пытаемся получить информацию, данные метаполя не передаются с нашим запросом.
Это приводит нас к изначально удручающему пониманию: Метаполи могут только быть доступны через Liquid
Так что мы можем сделать?
Метаполя полузащищены: вы должны знать, что пространство имен существует, и обращаться к нему в Liquid. Частично, я думаю, это должно обеспечить уровень защиты для приложений, которые полагаются на метаполя, чтобы делать то, что они делают. (Было бы не хорошо, если бы потенциальный клиент, который знает, как работает Shopify, мог открыть окно, которое показывает метаданные какого-либо приложения о том, чтобы претендовать на лучшую цену, например)
Так или иначе, нам нужно будет создать новые переменные, которые будут хранить нужные нам метаданные, а затем использовать эту переменную в цикле JS.
У нас есть несколько вариантов, и какой из них вы выбираете, зависит от вас. Вот две идеи:
Идея 1: Создание глобальных переменных на странице
Как правило, это самый простой способ, но создание большого количества глобальных переменных можно считать неаккуратным. Кроме того, Liquid отображается только при загрузке страницы, поэтому, если ваш сайт очень динамичный, вы можете столкнуться с ситуациями, когда действия клиента могут привести к тому, что вы не загрузите все метаданные.
Для этого мы создадим объект в Javascript, который будет использовать уникальный идентификатор для каждого продукта на странице, который нас может заинтересовать - наиболее очевидные варианты - либо идентификатор продукта, либо дескриптор продукта, так как оба гарантированно будут уникальными.
Поскольку мы сохраняем метаданные только для рассматриваемого приложения / функции, а не сохраняем каждое метаполе, которое может существовать в продукте, давайте создадим фрагмент с именем save-accentuate-metadata.liquid
для хранения логики:
<script>
// Initialize our global object only if it doesn't exist yet
window.AccentuateLookup = window.AccentuateLookup || {}
AccentuateLookup[{{ product.handle | json }}] = {{ product.metafields.accentuate | json }}
</script>
Теперь нам нужно просто включить его везде, где есть объект продукта - страницы продукта, циклы продукта коллекции и т. Д. Мы ожидаем переменную с именем product
во фрагменте, поэтому давайте разберемся с этим в наш фрагмент вызова:
{% include 'save-accentuate-metadata', product: product %}
Если есть вероятность, что наш код должен быть в состоянии запускаться на странице поиска, то для включения в него должна быть указана ссылка на любую переменную, вызываемую на странице поиска (часто result
):
{% if result.object_type == 'product' %}
{% include 'save-accentuate-metadata', product: result %}
{% endif %}
И, наконец, мы хотим убедиться, что сохранили все данные метаполя для товаров, находящихся в данный момент в корзине. Мы поместили бы этот вызов где-нибудь глобально, например, в layout / theme.liquid (или фрагмент, который мы включили в theme.liquid)
{% for item in cart.items %}
{% include 'save-accentuate-metadata', product: item.product %}
{% endfor %}
Теперь, когда мы сохранили всю эту информацию, мы можем получить к ней доступ в любом скрипте, который нам нужен, если у нас есть дескриптор продукта.
// Meanwhile, in some other script on the page:
if(typeof AccentuateLookup === 'undefined'){
console.error('No data initialized!')
}
var accentuate_data = AccentuateLookup[item.handle]
console.log('Our records show the following for' + item.title, accentuate_data)
Идея 2: Создание нашей собственной конечной точки
Это займет немного больше работы, но даст вам собственную конечную точку, которую вы можете использовать для получения нужных вам данных в любое время. Это позволяет вам более чутко реагировать на модные функции или приложения, работающие на вашем сайте, которые могут манипулировать корзиной или загружать товары, которых изначально не было на странице (например, приложения в стиле апселла). Обратите внимание, что при таком маршруте вам потребуется выполнить асинхронный вызов AJAX для получения данных, что может привести к задержке во время загрузки данных.
Чтобы создать собственную конечную точку, мы сначала создаем новый шаблон для типа объекта, с которого мы хотим получать данные. Давайте сделаем два: один для корзины, который предоставит все данные для наших товаров, а другой для отдельного продукта.
Начнем с создания шаблона с именем cart.accentuate.json.liquid
со следующим:
{% layout none %} {% comment %} That tells Shopify to ignore all the layout code/HTML, freeing us to create a simple JSON object {% endcomment %}
{
{% for item in cart.items %}
{% comment %}Output the JSON data, and append a comma unless we're on the last one{% endcomment %}
{{ item.handle | json }}: {{ item.product.metafields.accentuate | json }}{% unless forloop.last %},{% endunless %}
{% endfor %}
}
И на всякий случай, если мы хотим получить только один продукт, давайте создадим шаблон для product.accentuate.json.liquid
. Поскольку мы получаем конкретный продукт, нам, вероятно, не нужно ничего, кроме метаданных:
{% layout none %}
{{ product.metafields.accentuate | json }}
Теперь мы можем получить доступ к любому из них из любого произвольного фрагмента кода, используя вызовы AJAX, указав view
в строке запроса, которая соответствует суффиксу нашего шаблона. Например:
jQuery.ajax({
url:'/cart?view=accentuate.json',
success:function(unparsed_json){
var cart_data = JSON.parse(unparsed_json)
console.log('This just in from cart.accentuate.json:', cart_data)
}
})
var handle = 'sleepy-head'
jQuery.ajax({
url:'/products/' + handle + '?view=accentuate.json',
success:function(unparsed_json){
var cart_data = JSON.parse(unparsed_json)
console.log('This just in from product.accentuate.json:', cart_data)
}
})
Обратите внимание, что когда мы создаем пользовательскую конечную точку таким образом, Shopify будет обрабатывать свой ответ, как будто это обычная HTML-страница. Это может вызвать странное поведение AJAX-функций jQuery, если мы попытаемся указать, что ожидаем ответа JSON. Обнаружение всех неожиданных действий оставлено читателю в качестве упражнения, но вы должны понять, что вы хотите получить свою страницу, как если бы она была обычной HTML-страницей, а затем использовать JSON.parse
, чтобы превратить полученный текст в правильный объект JSON.
Надеюсь, это поможет вам завершить функцию, над которой вы работаете!
Отказ от ответственности: Весь приведенный выше код является свободным и не был проверен на опечатки. Если что-то не работает немедленно, пожалуйста, прокомментируйте, отредактируйте и / или проверьте на наличие очевидной плохой грамматики кода