shopify
WordPress is extremely popular with small businesses, but more and more product businesses are also opening up e-commerce stores using Shopify. It’s possible to keep an existing info site and use of the Shopify API with a custom page template to pull a feed of products from Shopify into a WordPress site.
WordPress在小型企业中非常受欢迎,但是越来越多的产品企业也在使用Shopify开辟电子商务商店。 可以保留现有的信息站点,并使用带有自定义页面模板的Shopify API,以将Shopify产品提要拉到WordPress站点中。
There is a working feed of products on this demo page, which pulls from a demo Shopify store, and the end result looks like this:
该演示页面上有一个有效的产品供稿, 该供稿来自Shopify演示店 ,最终结果如下所示:
Let’s get started!
让我们开始吧!
在Shopify端设置 (Set up on the Shopify Side)
In order to set up integration with Shopify, you’ll need to have a collection to pull into your WordPress page and a private app set up so that you can call into the Shopify API.
为了设置与Shopify的集成,您需要具有一个集合以拉入WordPress页面并设置一个私有应用程序,以便可以调用Shopify API。
确定您的收藏 (Identify Your Collection)
While you may be used to using the collection title or handle in Shopify templates, for integration purposes the primary identifier is the collection ID number. You can find the ID number for a given collection by editing the collection in the Shopify admin and looking at the end of the URL:
尽管您可能习惯在Shopify模板中使用集合标题或句柄,但出于集成目的,主要标识符是集合ID号。 您可以通过在Shopify管理员中编辑集合并查看URL的末尾来找到给定集合的ID号:
Make sure that your selected collection has a handful of products in it, and note that ID number for use on your WordPress site.
确保您选择的收藏集中有少量产品,并注意要在WordPress网站上使用的ID号。
创建一个私人应用 (Creating a Private App)
While you’re in Shopify’s admin, you will need to create a private app. This is what gives you access to your shop information via the Shopify API.
在Shopify的管理员中,您将需要创建一个私人应用。 这就是让您通过Shopify API访问商店信息的原因。
To create an app, head to the Apps page in the admin and click on the Private Apps button in the top right corner. On the next page, click the button to Create a Private App. You’ll need to give the app a title and you can optionally include a contact email address (if you don’t enter an email it will default to your user’s email address).
要创建应用,请转到管理员中的“应用”页面,然后单击右上角的“私人应用”按钮。 在下一页上,单击创建私人应用程序的按钮。 您需要给该应用命名,并且可以选择包括联系人电子邮件地址(如果您不输入电子邮件,它将默认为您用户的电子邮件地址)。
Click the save button and your app is live! Click on the title of the app in the Private Apps list to get the full set of authentication details you’ll need to connect via the API. The sample URL at the very bottom has the correct formatting, so that’s a great place to start.
单击保存按钮,您的应用程序已上线! 在“私人应用程序”列表中单击应用程序的标题,以获取您需要通过API连接的完整身份验证详细信息。 最底部的示例URL具有正确的格式,因此这是一个很好的起点。
The full Example URL is what you’d use to access the Orders information for your shop via the API, so you’ll want to note just the beginning of the URL. In this example, you’d note the following:
完整的示例URL是用于通过API访问商店的“订单”信息的内容,因此您只需要注意URL的开头即可。 在此示例中,您将注意以下内容:
https://c6bd98e6ae2e0c6945208ec441340af0:2fea2ea43af949b6623e140a82cd482f@just-a-demo.myshopify.com
Just to note – for account security purposes this is not a working URL, so please don’t try to use it for your own test purposes.
请注意-为了帐户安全起见,这不是有效的URL,因此请不要尝试将其用于您自己的测试目的。
Once you have the collection ID and the private app URL, you are all set on the Shopify side!
获得收藏集ID和私人应用程序URL后,就可以在Shopify端设置好一切!
WordPress设置 (WordPress Set Up)
The bulk of the integration happens on the WordPress side, where you’ll create a custom template to display your selected collection. First, make sure that you are working within a child theme or a completely custom theme that won’t be overwritten on update.
集成的大部分发生在WordPress端,您将在其中创建一个自定义模板以显示您选择的集合。 首先,请确保您正在使用子主题或完全自定义主题,而该主题不会在更新时被覆盖。
创建一个新页面模板 (Create a New Page Template)
For this demo, we’ll create a custom page template with our collection feed, so the first step is to create a new file in the theme with the file name page-shopify.php
. The initial contents of this page should look something like this:
对于此演示,我们将使用集合供稿创建一个自定义页面模板,因此第一步是在主题中使用文件名page-shopify.php
创建一个新文件。 该页面的初始内容应类似于以下内容:
<?php
/**
* Template Name: Shopify Collection Demo
*
*/
get_header(); ?>
<div id="primary" class="full-width">
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<h1 class="page-title"><?php the_title(); ?></h1>
</header><!-- .entry-header -->
<div class="entry-content">
<?php the_content(); ?>
</div><!-- .entry-content -->
</article>
<?php endwhile; ?>
</div><!-- #primary -->
<?php get_footer(); ?>
You may want to base your HTML structure around an existing page in your template, since your template may not use the same classes, IDs, or layout HTML as the above example. I’ve kept the page title and body content in my template so that I can have lead-in text above the product grid.
您可能希望将HTML结构作为模板中现有页面的基础,因为模板可能不使用与上述示例相同的类,ID或布局HTML。 我将页面标题和正文内容保留在模板中,以便可以在产品网格上方添加导入文本。
Save your new file and, if applicable, upload it to your development server.
保存新文件,如果适用,将其上传到开发服务器。
创建页面并分配模板 (Create a Page and Assign the Template)
The most important feature to maintain from the custom template example above is the template name in the first comment block – this allows you to assign this template to a page in your WordPress admin.
上面的自定义模板示例中要维护的最重要功能是第一个注释块中的模板名称-这使您可以将此模板分配给WordPress管理员中的页面。
That’s what you’ll want to do next – create a new page in WordPress and assign your new template to that page:
这就是您接下来要做的–在WordPress中创建一个新页面并将新模板分配给该页面:
At this point, you’ll be able to view your new page with your custom template applied but there won’t be much to see since we haven’t added any of the integration code yet.
此时,您将能够在应用了自定义模板的情况下查看新页面,但是由于我们尚未添加任何集成代码,因此看不到太多内容。
可选:为Shopify数据创建自定义字段 (Optional: Create Custom Fields for Shopify Data)
While you don’t strictly have to do this next step, I like to use custom fields for the Shopify data such as the collection ID and API authentication URL. In contrast with hard-coding that data into the template, custom fields let me easily change that information if I want to in the future. While the API URL may not change, you may decide to feature a different collection and it’s nice to not have to edit the template to make that change.
尽管您不必严格执行下一步,但我想对Shopify数据使用自定义字段,例如集合ID和API身份验证URL。 与将数据硬编码到模板中相比,自定义字段使我将来可以轻松地更改该信息。 尽管API URL可能不会更改,但是您可以决定使用其他集合,并且不必编辑模板即可进行更改。
I use the Advanced Custom Fields (ACF) plugin for this type of thing because it’s free, quick, easy, and creates a nice interface for the custom fields. You’ll want to set up three fields:
我将Advanced Custom Fields(ACF)插件用于这种类型的事情,因为它是免费,快速,简便的,并且为自定义字段创建了一个不错的界面。 您将要设置三个字段:
Once these fields are set up and applied to the custom page template, you’ll see them when you edit your new page and you can use them to enter the data you collected from your Shopify account earlier:
设置好这些字段并将其应用于自定义页面模板后,您将在编辑新页面时看到它们,并可以使用它们输入您先前从Shopify帐户收集的数据:
嵌入收藏 (Embed the Collection)
Now that the setup is done on both sites, it’s time to get into the bulk of the custom code to pull in your collection via the Shopify API. For reference, you can access the full code used in my demo template in this GitHub Gist.
现在,已经在两个站点上都完成了设置,是时候进入大量自定义代码了,以通过Shopify API提取集合了。 作为参考,您可以在GitHub Gist中访问我的演示模板中使用的完整代码。
I started out by creating a new div just under my regular entry-content
area to hold my feed:
我首先在常规entry-content
区域下面创建一个新的div来保存我的供稿:
<div class="row product-feed"></div>
分配基本变量 (Assign Base Variables)
To get started, we’ll create a couple of PHP variables to hold the Shopify information.
首先,我们将创建几个PHP变量来保存Shopify信息。
具有高级自定义字段 (With Advanced Custom Fields)
If you used Advanced Custom Fields, your variable setup would look like this:
如果使用了高级自定义字段,则变量设置将如下所示:
// Set variables
$api_url = get_field( 'shopify_app_api_url' );
$shop_url = get_field( 'shopify_site_url' );
$collection_id = get_field( 'collection_id' );
Again, the benefit here is that you can change these values in your WordPress admin without needing to touch your template file.
同样,这样做的好处是您可以在WordPress管理员中更改这些值,而无需触摸模板文件。
硬编码您的价值观 (Hard-Coding Your Values)
If you didn’t use custom fields, you can still set up the same variables, but you’ll hard code the values in place, like so:
如果您不使用自定义字段,则仍然可以设置相同的变量,但是将硬编码这些值,如下所示:
// Set variables
$api_url = 'https://c6bd98e6ae2e0c6945208ec441340af0:2fea2ea43af949b6623e140a82cd482f@just-a-demo.myshopify.com';
$shop_url = 'http://just-a-demo.myshopify.com';
$collection_id = '26542309';
From this point forward, we’ll use these variables in the code so it won’t matter which method you used.
从现在开始,我们将在代码中使用这些变量,因此使用哪种方法都没有关系。
访问API数据 (Access the API Data)
The Shopify API is fairly well documented and has a wide variety of access points. We’ll be using two of those access points in this tutorial, collect and product.
Shopify API的文档非常齐全,并且具有各种各样的访问点。 在本教程中,我们将使用其中两个访问点, collect和product 。
获取产品列表 (Get the List of Products)
A collect is a kind of funny unit in that it’s not something you ever interact with in the Shopify admin, but it’s the object that holds information about which products are in a custom collection. The collect will output an array of products in the collection, including each product’s ID
收藏是一种有趣的单元,因为它不是您在Shopify管理员中曾与之互动的东西,而是它是保存有关哪些商品在自定义收藏中的信息的对象。 集合将输出集合中的一系列产品,包括每个产品的ID
As such, the first file we’ll pull from the API is the collect data for the featured collection, which we will do by setting up a variable equivalent to the URL for the collect JSON file:
因此,我们将从API中提取的第一个文件是精选集合的收集数据,我们将通过设置一个等效于collect JSON文件的URL的变量来做到这一点:
// Create the API URL for the Shopify collect
$collects_url = $api_url . '/admin/collects.json?collection_id=' . $collection_id . '&limit=3';
The full format for this URL is API URL
+ /admin/collects.json?collection_id=
+ COLLECTION ID
followed by optional parameters. We’ve used our variables for the API URL and collection ID, and also added a parameter to limit the number of products returned to 3 (if you want to return more or fewer products, you could edit that final digit on the URL).
此URL的完整格式为API URL
+ /admin/collects.json?collection_id=
+ COLLECTION ID
后跟可选参数。 我们已将变量用于API URL和集合ID,还添加了一个参数以将返回的产品数限制为3(如果要返回更多或更少的产品,则可以在URL上编辑该最后一位数字)。
获取文件内容(带有缓存) (Get the File Contents (with Caching))
Now that we have that URL, we’ll want to get the file it points to, but in order to prevent hitting Shopify’s API limits (and to improve performance), we can use a WordPress transient to temporarily cache the file.
现在我们有了该URL,我们将要获取它指向的文件,但是为了防止达到Shopify的API限制(并提高性能),我们可以使用WordPress临时方法来临时缓存该文件。
The next code in the file checks for a transient with the name shopify_product_feed
. If it doesn’t find one, it gets the file from Shopify and sets the transient to store that data for 4 hours:
文件中的下一个代码检查名称为shopify_product_feed
的瞬态。 如果找不到,则从Shopify获取文件,并将瞬态设置为将数据存储4小时:
// Use a transient for the feed URL (performance boost)
if ( false === ( $collects_content = get_transient( 'shopify_product_feed' ) ) ) {
$collects_content = @file_get_contents( $collects_url );
// Put the results in a transient. Expire after 4 hours.
set_transient( 'shopify_product_feed', $collects_content, 4 * HOUR_IN_SECONDS );
}
// Decode the JSON in the file
$collects = json_decode( $collects_content, true );
The only risk with this transient is that your feed may be a bit behind your collection – if you were to change the products in your collection on Shopify, that change may not appear on WordPress for up to four hours (or however long you set the transient). In most cases that’s an acceptable risk for the performance gains.
这种暂时性的唯一风险是,您的供稿可能会落后于您的收藏集–如果您要在Shopify上更改收藏集中的产品,则更改最多可能会在WordPress上显示四个小时(或者您设置了短暂的)。 在大多数情况下,这是性能可接受的风险。
Notice that there is an @
symbol at the beginning of @file_get_contents
. That suppresses PHP errors if there is a problem getting the file contents, which could happen if you do hit an API limit. You may want to remove that while you’re testing your implementation because you may want those errors to appear until you have everything working.
注意, @
@file_get_contents
的开头有一个@
符号。 如果获取文件内容时出现问题,这可以抑制PHP错误,如果您确实遇到API限制,则可能会发生这种情况。 您可能希望在测试实现时将其删除,因为您可能希望这些错误在一切正常工作之前出现。
The last line in the above snippet decodes the JSON data in the file and stores it in an array.
上面代码段的最后一行解码文件中的JSON数据,并将其存储在数组中。
遍历收集 (Loop Through the Collect)
Now that we’ve got the initial array of product data for the collect, we’ll loop through it and create a set of variables that we’ll use later on to display the data in the template. This loop starts out:
现在我们已经有了要收集的产品数据的初始数组,我们将遍历它并创建一组变量,稍后将使用它们在模板中显示数据。 此循环开始:
// Reset variant inventory count
$variant_inventory = 0;
// Loop through products in the collection
for ( $prod = 0; $prod < 3; $prod++ ) {
// Get the product ID for the current product
$product_id = $collects['collects'][$prod]['product_id'];
The first line sets the inventory counter to 0 – this is something we want to do before each instance of the loop so that we’re able to independently check inventory for each product.
第一行将库存计数器设置为0 –这是我们希望在循环的每个实例之前执行的操作,以便我们能够独立检查每种产品的库存。
Next, we start a for
loop. If you’ve changed your product number (by changing the limit parameter in the collect URL) you’ll want to also update the limit in this line ($prod ).
接下来,我们开始一个for
循环。 如果您更改了产品编号(通过更改collect URL中的limit参数),则还需要更新此行中的限制( $prod ).
Within the loop, we start out by getting the product ID for the current product and assigning it to the variable $product_id
.
在循环中,我们首先获取当前产品的产品ID,然后将其分配给变量$product_id
。
通过API访问产品数据 (Access Product Data via the API)
Once we’ve got the product ID, we can go back to the Shopify API to get all the data we’ll display for that product. The format for this API call is:
获得产品ID后,我们可以返回Shopify API以获取我们将为该产品显示的所有数据。 此API调用的格式为:
// Get the product data from the API (using the ID)
$product_url = $api_url . '/admin/products/' . $product_id . '.json?fields=images,title,variants,handle';
// Decode the JSON for the product data
$product_json = json_decode( @file_get_contents( $product_url ), true );
Just like with the collect, we’re putting together the URL for the product data, but this time we’re inserting the $product_id
variable we just created to grab a particular product’s data. The parameters at the end of the URL allow us to limit which data gets returned by the API – in this case, we’re just getting the product title, handle, images, and variant data.
就像收集一样,我们将产品数据的URL放在一起,但是这次我们要插入刚刚创建的$product_id
变量以获取特定产品的数据。 URL末尾的参数使我们能够限制API返回哪些数据–在这种情况下,我们仅获取产品标题,句柄,图像和变体数据。
While it’s a good idea to cache the collect data, I would advise against caching product data (or if you do cache it, setting a lower expiration time frame). This is because product data such as availability is more likely to change at any given time, and you likely want your feed to reflect up to the moment data on pricing and availability.
虽然缓存收集数据是个好主意,但我建议不要缓存产品数据(或者如果要缓存它,请设置较短的到期时间)。 这是因为诸如可用性之类的产品数据在任何给定时间都可能会发生变化,并且您可能希望您的Feed反映价格和可用性方面的最新数据。
As such, there’s no transient for this file, instead the product data is accessed directly and the resulting array of information for the product is assigned to the variable $product_json
.
因此,此文件没有任何暂态,而是直接访问产品数据,并且将产品的结果信息数组分配给变量$product_json
。
设置产品数据变量 (Setting Product Data Variables)
The first few pieces of data we’ll display for each product are easy enough to get from the array:
我们将为每种产品显示的前几数据很容易从数组中获取:
// Set some variables for product data
$current_product = $product_json['product'];
$product_handle = $current_product['handle'];
$product_title = $current_product['title'];
This snippet sets a variable for the current product, and then assigns the product handle and title to a set of variables.
此代码段为当前产品设置了一个变量,然后将产品句柄和标题分配给一组变量。
Next, we’ll get the product image source. This is a little bit trickier because Shopify sends the URL for the original (full size) image, which is usually much larger than what you’ll want to display. We can avoid serving a gigantic image unnecessarily by modifying that image source with Shopify’s file naming convention to get a smaller image size:
接下来,我们将获得产品图像源。 这有点棘手,因为Shopify发送原始(全尺寸)图像的URL,该URL通常比您要显示的要大得多。 通过使用Shopify的文件命名约定修改该图像源以减小图像尺寸,我们可以避免不必要地提供巨大的图像:
// Get the product image and modify the file name to get the large size thumbnail
$image_src_parts = pathinfo( $current_product['images'][0]['src'] );
$product_image_src = $image_src_parts['dirname'] . '/' . $image_src_parts['filename'] . '_large.' . $image_src_parts['extension'];
In this snippet, we’ve used PHP’s pathinfo to break down the image source and then we’re rebuilding it and adding the _large
string to specify which size thumbnail to return. This is reliant on Shopify’s file naming conventions for image sizes, but those have remained consistent over time so I feel it’s a safe move.
在此代码段中,我们使用了PHP的pathinfo分解图像源,然后对其进行重建,并添加_large
字符串以指定要返回的大小缩略图。 这依赖于Shopify的图像大小文件命名约定,但是随着时间的推移这些约定一直保持一致,因此我认为这是一个安全的举动。
The last set of information we’ll display about each product is its availability and price. We’ll use inventory to determine if a product should show as sold out, and we’ll get information about variants and pricing to determine whether to show a single price or a range.
我们将显示的有关每种产品的最后一组信息是其可用性和价格。 我们将使用库存来确定产品是否应显示为已售完,并且我们将获取有关变体和价格的信息,以确定是显示单个价格还是范围。
// Get product variant information, including inventory and pricing
$variants = $current_product['variants'];
$variant_count = count( $variants );
$variant_price = 0;
$variant_prices = array();
if ( $variant_count > 1 ) :
for ( $v = 0; $v < $variant_count; $v++ ) {
$variant_inventory += $variants[$v]['inventory_quantity'];
$variant_prices[] = $variants[$v]['price'];
}
$price_min = min( $variant_prices );
$price_max = max( $variant_prices );
else :
$variant_price = $variants[0]['price'];
$variant_inventory = $variants[0]['inventory_quantity'];
endif;
?>
Variants are an array of their own, so this snippet assigns that array to a variable then counts how many variants exist. It then sets a the price to zero to start out, which serves as a reset for each time we loop through a different product.
变体是它们自己的数组,因此此代码段将该数组分配给变量,然后计算存在多少变体。 然后,它将价格设置为零开始,这是每次我们浏览不同产品时的重置。
If there is more than one variant, we loop through the variants and add up the total inventory count while also creating an array of the prices for all the variants. From that array, we calculate the minimum price and the maximum price, which we would then display as a range below the product title.
如果存在多个变体,我们将遍历所有变体并加总库存数量,同时还会为所有变体创建一系列价格。 从该数组中,我们计算出最低价格和最高价格,然后将其显示为产品标题下方的范围。
If there is only one variant, we get the price and inventory for that single variant instead.
如果只有一个变体,我们将获得该单个变体的价格和库存。
显示每个产品 (Display Each Product)
Now that we have all the data, we’ll display set to variables, we can set up the display.
现在我们有了所有数据,我们将显示设置为变量,我们可以设置显示。
完整标记 (Full Markup)
<div class="product-feed-item">
<a href="<?php echo $shop_url; ?>/products/<?php echo $product_handle; ?>">
<img src="<?php echo $product_image_src; ?>" alt="<?php echo $product_title; ?>"/>
<h3><?php echo $product_title; ?></h3>
<?php if ( $variant_inventory > 0 ) : ?>
<?php if ( $variant_price > 0 ) : ?>
<span class="price small"><?php if ( $variant_price > 0 ) : ?>$<?php echo $variant_price; ?><?php else : ?>FREE<?php endif; ?></span>
<?php elseif ( ( $price_min > 0 ) && ( $price_max > 0 ) ) : ?>
<span class="price small">$<?php echo $price_min; ?> - $<?php echo $price_max; ?></span>
<?php endif; ?>
<?php else : ?>
<span class="sold-out">OUT OF STOCK</span>
<?php endif; ?>
</a>
</div>
Each product is wrapped in a div with the class `product-feed-item` for styling purposes, then has the image with the product title as the ALT tag. The URL to the product is created by combining the shop URL with the product handle.
每个产品都包装在一个带有“ product-feed-item”类的div中,用于样式设计,然后将带有产品标题的图像作为ALT标签。 产品的URL是通过将商店URL与产品句柄组合而创建的。
Underneath the image, the product title is displayed in an
在图片下方,产品标题显示在
元件。
产品库存和价格
( element.Product Inventory and Price
)Finally, there are some conditionals to check whether the product is in stock and whether it has a range of prices:
最后,有一些条件可以检查产品是否有现货以及价格范围是否:
<?php if ( $variant_inventory > 0 ) : ?>
<?php if ( $variant_price > 0 ) : ?>
<span class="price small"><?php if ( $variant_price > 0 ) : ?>$<?php echo $variant_price; ?><?php else : ?>FREE<?php endif; ?></span>
<?php elseif ( ( $price_min > 0 ) && ( $price_max > 0 ) ) : ?>
<span class="price small">$<?php echo $price_min; ?> - $<?php echo $price_max; ?></span>
<?php endif; ?>
<?php else : ?>
<span class="sold-out">OUT OF STOCK</span>
<?php endif; ?>
If the product inventory is greater than zero, the price is displayed (with a range if appropriate), but if it’s less than zero the words “OUT OF STOCK” display in place of the price.
如果产品库存大于零,则显示价格(在适当的范围内),但如果小于零,则显示“缺货”字样代替价格。
The last few lines in the sample file close out the product markup and the product loop.
示例文件中的最后几行关闭了产品标记和产品循环。
样式输出 (Styling the Output)
With the product feed in place, the only thing left to do is some styling. I’ve included some basic styles inline in my demo, just to give the grid some shape:
将产品送入原位后,剩下要做的就是样式。 我在演示中包括了一些基本样式,只是为了给网格一些形状:
.product-feed-item {
display: inline-block;
vertical-align: top;
width: 31%;
margin-right: 2%;
text-align: center;
}
.product-feed-item img {
max-width: 100%;
height: auto;
}
结语 (Wrap Up)
There are a lot of potential applications for integrating the Shopify API with WordPress beyond featuring a single collection on a page. Sites I’ve created have integrated featured products into each blog post, and have gone so far as to allow you to add a product to your Shopify cart from within WordPress. Integrating a single collection is a great first step to getting more familiar with the API and how it works in a WordPress context, but the sky is the limit!
除了在页面上具有单个集合之外,还有许多将Shopify API与WordPress集成的潜在应用程序。 我创建的网站已将特色产品集成到每篇博客文章中,并且走得很远,以至于您可以从WordPress中将产品添加到Shopify购物车中。 集成单个集合是更好地了解API及其在WordPress上下文中的工作方式的重要第一步,但是天空是极限!
翻译自: https://www.sitepoint.com/using-the-shopify-api-with-wordpress/
shopify